Compare commits

..

23 Commits
1.1.0 ... 1.3.1

Author SHA1 Message Date
LambdAurora
24f7054eff 🔖 LambdaControls v1.3.1: Fix broken inventory interactions and virtual mouse bug. 2020-06-28 22:22:19 +02:00
LambdAurora
4669e446dc 🔖 LambdaControls v1.3.0: Update to Minecraft 1.16.1. 2020-06-27 19:05:20 +02:00
LambdAurora
ff672f05a1 🔖 LambdaControls v1.2.0: Fast block placement, virtual mouse, etc. 2020-06-27 18:40:35 +02:00
LambdAurora
756e7d102d Improve rotation algorithm. 2020-06-27 18:21:46 +02:00
LambdAurora
e676a37c7f Update to 1.16. 2020-06-27 16:08:10 +02:00
LambdAurora
45dd94fd34 🐛 Fix some little bugs. 2020-02-18 19:20:32 +01:00
LambdAurora
f8cc1fcc20 🚧 More WIP on REI as hooking into it is quite difficult. 2020-02-18 18:09:50 +01:00
LambdAurora
d56126c680 🚧 WIP on REI compatiblity. 2020-02-18 10:43:27 +01:00
LambdAurora
5a2fad4445 🚧 WIP on REI compatiblity. 2020-02-18 10:01:39 +01:00
LambdAurora
0eadc054b6 Add proper fast block placing. 2020-02-17 22:52:59 +01:00
LambdAurora
07a296603a 🚧 WIP on fast block placing. 2020-02-17 12:05:06 +01:00
LambdAurora
8e082404f9 Add always more features. 2020-02-16 23:20:21 +01:00
LambdAurora
8efddb24b0 🎨 White outline for front block placing. 2020-02-16 10:55:21 +01:00
LambdAurora
581757aaee Add new recipe book controls and front block outline. 2020-02-16 00:46:03 +01:00
LambdAurora
40dc8d424c 🎨 Update README. 2020-02-15 00:20:18 +01:00
LambdAurora
230a9f6424 🎨 Update README. 2020-02-15 00:19:11 +01:00
LambdAurora
ba01df036b 🎨 Update README. 2020-02-15 00:02:02 +01:00
LambdAurora
ff90d55351 Improve HUD, add autojump option. 2020-02-14 19:30:54 +01:00
LambdAurora
efc2d6284d 🎨 Quick code cleaning. 2020-02-13 11:54:17 +01:00
LambdAurora
9e2c4720e9 🚧 WIP on better button tip rendering. 2020-02-13 11:51:29 +01:00
LambdAurora
8063116820 Some refactor and add missing behaviors in some GUIs. 2020-02-13 00:28:58 +01:00
LambdAurora
0050b0216c 🔖 LambdaControls v1.1.1: Add more precision in the fly drifting tooltips. 2020-02-05 15:39:19 +01:00
LambdAurora
e13569b71d Add precision to some tooltips and prepare for the fast/accurate block placement feature. 2020-02-05 13:28:23 +01:00
58 changed files with 2251 additions and 673 deletions

4
.gitignore vendored
View File

@@ -1,11 +1,13 @@
# #
# LambdAurora's ignore file # LambdAurora's ignore file
# #
# v0.12 # v0.13
# JetBrains # JetBrains
.idea/ .idea/
*.iml *.iml
*.ipr
*.iws
## Intellij IDEA ## Intellij IDEA
out/ out/
## CLion ## CLion

View File

@@ -5,7 +5,7 @@
![Environment: Client](https://img.shields.io/badge/environment-client-1976d2?style=flat-square) ![Environment: Client](https://img.shields.io/badge/environment-client-1976d2?style=flat-square)
![Mod loader: Fabric](https://img.shields.io/badge/modloader-Fabric-1976d2?style=flat-square&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAAsTAAALEwEAmpwYAAAFHGlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDIgNzkuMTYwOTI0LCAyMDE3LzA3LzEzLTAxOjA2OjM5ICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOCAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDE4LTEyLTE2VDE2OjU0OjE3LTA4OjAwIiB4bXA6TW9kaWZ5RGF0ZT0iMjAxOS0wNy0yOFQyMToxNzo0OC0wNzowMCIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAxOS0wNy0yOFQyMToxNzo0OC0wNzowMCIgZGM6Zm9ybWF0PSJpbWFnZS9wbmciIHBob3Rvc2hvcDpDb2xvck1vZGU9IjMiIHBob3Rvc2hvcDpJQ0NQcm9maWxlPSJzUkdCIElFQzYxOTY2LTIuMSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDowZWRiMWMyYy1mZjhjLWU0NDEtOTMxZi00OTVkNGYxNGM3NjAiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MGVkYjFjMmMtZmY4Yy1lNDQxLTkzMWYtNDk1ZDRmMTRjNzYwIiB4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ9InhtcC5kaWQ6MGVkYjFjMmMtZmY4Yy1lNDQxLTkzMWYtNDk1ZDRmMTRjNzYwIj4gPHhtcE1NOkhpc3Rvcnk+IDxyZGY6U2VxPiA8cmRmOmxpIHN0RXZ0OmFjdGlvbj0iY3JlYXRlZCIgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDowZWRiMWMyYy1mZjhjLWU0NDEtOTMxZi00OTVkNGYxNGM3NjAiIHN0RXZ0OndoZW49IjIwMTgtMTItMTZUMTY6NTQ6MTctMDg6MDAiIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE4IChXaW5kb3dzKSIvPiA8L3JkZjpTZXE+IDwveG1wTU06SGlzdG9yeT4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4/HiGMAAAAtUlEQVRYw+XXrQqAMBQF4D2P2eBL+QIG8RnEJFaNBjEum+0+zMQLtwwv+wV3ZzhhMDgfJ0wUSinxZUQWgKos1JP/AbD4OneIDyQPwCFniA+EJ4CaXm4TxAXCC0BNHgLhAdAnx9hC8PwGSRtAFVMQjF7cNTWED8B1cgwW20yfJgAvrssAsZ1cB3g/xckAxr6FmCDU5N6f488BrpCQ4rQBJkiMYh4ACmLzwOQF0CExinkCsvw7vgGikl+OotaKRwAAAABJRU5ErkJggg==) ![Mod loader: Fabric](https://img.shields.io/badge/modloader-Fabric-1976d2?style=flat-square&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAAsTAAALEwEAmpwYAAAFHGlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDIgNzkuMTYwOTI0LCAyMDE3LzA3LzEzLTAxOjA2OjM5ICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOCAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDE4LTEyLTE2VDE2OjU0OjE3LTA4OjAwIiB4bXA6TW9kaWZ5RGF0ZT0iMjAxOS0wNy0yOFQyMToxNzo0OC0wNzowMCIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAxOS0wNy0yOFQyMToxNzo0OC0wNzowMCIgZGM6Zm9ybWF0PSJpbWFnZS9wbmciIHBob3Rvc2hvcDpDb2xvck1vZGU9IjMiIHBob3Rvc2hvcDpJQ0NQcm9maWxlPSJzUkdCIElFQzYxOTY2LTIuMSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDowZWRiMWMyYy1mZjhjLWU0NDEtOTMxZi00OTVkNGYxNGM3NjAiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MGVkYjFjMmMtZmY4Yy1lNDQxLTkzMWYtNDk1ZDRmMTRjNzYwIiB4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ9InhtcC5kaWQ6MGVkYjFjMmMtZmY4Yy1lNDQxLTkzMWYtNDk1ZDRmMTRjNzYwIj4gPHhtcE1NOkhpc3Rvcnk+IDxyZGY6U2VxPiA8cmRmOmxpIHN0RXZ0OmFjdGlvbj0iY3JlYXRlZCIgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDowZWRiMWMyYy1mZjhjLWU0NDEtOTMxZi00OTVkNGYxNGM3NjAiIHN0RXZ0OndoZW49IjIwMTgtMTItMTZUMTY6NTQ6MTctMDg6MDAiIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE4IChXaW5kb3dzKSIvPiA8L3JkZjpTZXE+IDwveG1wTU06SGlzdG9yeT4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4/HiGMAAAAtUlEQVRYw+XXrQqAMBQF4D2P2eBL+QIG8RnEJFaNBjEum+0+zMQLtwwv+wV3ZzhhMDgfJ0wUSinxZUQWgKos1JP/AbD4OneIDyQPwCFniA+EJ4CaXm4TxAXCC0BNHgLhAdAnx9hC8PwGSRtAFVMQjF7cNTWED8B1cgwW20yfJgAvrssAsZ1cB3g/xckAxr6FmCDU5N6f488BrpCQ4rQBJkiMYh4ACmLzwOQF0CExinkCsvw7vgGikl+OotaKRwAAAABJRU5ErkJggg==)
![Version](https://img.shields.io/github/v/tag/LambdAurora/LambdaControls?label=version&style=flat-square) ![Version](https://img.shields.io/github/v/tag/LambdAurora/LambdaControls?label=version&style=flat-square)
[![CurseForge](https://cf.way2muchnoise.eu/title/354231.svg)](https://www.curseforge.com/minecraft/mc-mods/lambdacontrols) [![CurseForge](http://cf.way2muchnoise.eu/title/354231.svg)](https://www.curseforge.com/minecraft/mc-mods/lambdacontrols)
A Fabric Minecraft mod which adds better controls like controller support. A Fabric Minecraft mod which adds better controls like controller support.

View File

@@ -27,6 +27,20 @@ allprojects {
classifier = "sources" classifier = "sources"
from sourceSets.main.allSource from sourceSets.main.allSource
} }
publishing {
repositories {
mavenLocal()
maven {
name = "GithubPackages"
url = uri("https://maven.pkg.github.com/LambdAurora/LambdaControls")
credentials {
username = project.findProperty("gpr.user") ?: System.getenv("USERNAME")
password = project.findProperty("gpr.key") ?: System.getenv("TOKEN")
}
}
}
}
} }
/* /*

View File

@@ -1,5 +1,6 @@
plugins { plugins {
id 'java-library' id 'java-library'
id 'maven-publish'
} }
archivesBaseName = project.archives_base_name + "-core" archivesBaseName = project.archives_base_name + "-core"
@@ -15,3 +16,17 @@ java {
sourceCompatibility = JavaVersion.VERSION_1_8 sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8
} }
publishing {
publications {
mavenJava(MavenPublication) {
// add all the jars that should be included when publishing to maven
artifact(jar) {
builtBy jar
}
artifact(sourcesJar) {
builtBy sourcesJar
}
}
}
}

View File

@@ -21,13 +21,14 @@ import java.util.Optional;
* Represents a feature. * Represents a feature.
* *
* @author LambdAurora * @author LambdAurora
* @version 1.1.0 * @version 1.2.0
* @since 1.1.0 * @since 1.1.0
*/ */
public class LambdaControlsFeature implements Nameable public class LambdaControlsFeature implements Nameable
{ {
private static final List<LambdaControlsFeature> FEATURES = new ArrayList<>(); private static final List<LambdaControlsFeature> FEATURES = new ArrayList<>();
public static final LambdaControlsFeature FRONT_BLOCK_PLACING = new LambdaControlsFeature("front_block_placing", true, false); public static final LambdaControlsFeature FRONT_BLOCK_PLACING = new LambdaControlsFeature("front_block_placing", true, false);
public static final LambdaControlsFeature FAST_BLOCK_PLACING = new LambdaControlsFeature("fast_block_placing", true, true);
private final String key; private final String key;
private final boolean defaultAllowed; private final boolean defaultAllowed;
@@ -155,5 +156,6 @@ public class LambdaControlsFeature implements Nameable
static { static {
FEATURES.add(FRONT_BLOCK_PLACING); FEATURES.add(FRONT_BLOCK_PLACING);
FEATURES.add(FAST_BLOCK_PLACING);
} }
} }

View File

@@ -1,9 +1,10 @@
plugins { plugins {
id 'fabric-loom' version '0.2.6-SNAPSHOT' id 'fabric-loom' version '0.4-SNAPSHOT'
id 'java-library' id 'java-library'
id 'maven-publish' id 'maven-publish'
} }
version = "${project.mod_version}+${project.minecraft_version}"
archivesBaseName = project.archives_base_name + "-fabric" archivesBaseName = project.archives_base_name + "-fabric"
minecraft { minecraft {
@@ -42,12 +43,13 @@ dependencies {
// Fabric API. This is technically optional, but you probably want it anyway. // Fabric API. This is technically optional, but you probably want it anyway.
modApi "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" modApi "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
modCompile "io.github.prospector:modmenu:1.8.5+build.23" modCompile "io.github.prospector:modmenu:${project.modmenu_version}"
modCompile "com.github.lambdaurora:spruceui:${project.spruceui_version}" modCompile "com.github.lambdaurora:spruceui:${project.spruceui_version}"
include "com.github.lambdaurora:spruceui:${project.spruceui_version}" include "com.github.lambdaurora:spruceui:${project.spruceui_version}"
// Compatibility mods // Compatibility mods
modCompile "io.github.joaoh1:okzoomer:2.1.0-beta.2" modCompile "io.github.joaoh1:okzoomer:4.0.0-alpha.3.1.16.pre5"
modCompile "me.shedaniel:RoughlyEnoughItems:4.5.5"
api project(":core") api project(":core")
shadow project(":core") shadow project(":core")
@@ -90,4 +92,20 @@ jar {
} }
} }
// configure the maven publication
publishing {
publications {
mavenJava(MavenPublication) {
// add all the jars that should be included when publishing to maven
artifact(remapJar) {
builtBy remapJar
}
artifact(sourcesJar) {
builtBy remapSourcesJar
}
}
}
}
build.dependsOn(":core:build") build.dependsOn(":core:build")
publish.dependsOn(":core:publish")

View File

@@ -15,8 +15,9 @@ import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.network.ServerSidePacketRegistry; import net.fabricmc.fabric.api.network.ServerSidePacketRegistry;
import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.FabricLoader;
import net.fabricmc.loader.api.ModContainer; import net.fabricmc.loader.api.ModContainer;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.text.TranslatableText;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import net.minecraft.util.PacketByteBuf;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -28,7 +29,7 @@ import java.util.Optional;
* Represents the LambdaControls mod. * Represents the LambdaControls mod.
* *
* @author LambdAurora * @author LambdAurora
* @version 1.1.0 * @version 1.3.0
* @since 1.0.0 * @since 1.0.0
*/ */
public class LambdaControls implements ModInitializer public class LambdaControls implements ModInitializer
@@ -38,6 +39,8 @@ public class LambdaControls implements ModInitializer
public static final Identifier FEATURE_CHANNEL = new Identifier(LambdaControlsConstants.FEATURE_CHANNEL.toString()); public static final Identifier FEATURE_CHANNEL = new Identifier(LambdaControlsConstants.FEATURE_CHANNEL.toString());
public static final Identifier HELLO_CHANNEL = new Identifier(LambdaControlsConstants.HELLO_CHANNEL.toString()); public static final Identifier HELLO_CHANNEL = new Identifier(LambdaControlsConstants.HELLO_CHANNEL.toString());
public static final TranslatableText NOT_BOUND_TEXT = new TranslatableText("lambdacontrols.not_bound");
public final Logger logger = LogManager.getLogger("LambdaControls"); public final Logger logger = LogManager.getLogger("LambdaControls");
@Override @Override

View File

@@ -9,7 +9,6 @@
package me.lambdaurora.lambdacontrols.client; package me.lambdaurora.lambdacontrols.client;
import com.mojang.blaze3d.platform.GlStateManager;
import me.lambdaurora.lambdacontrols.ControlsMode; import me.lambdaurora.lambdacontrols.ControlsMode;
import me.lambdaurora.lambdacontrols.LambdaControls; import me.lambdaurora.lambdacontrols.LambdaControls;
import me.lambdaurora.lambdacontrols.LambdaControlsConstants; import me.lambdaurora.lambdacontrols.LambdaControlsConstants;
@@ -17,25 +16,23 @@ import me.lambdaurora.lambdacontrols.LambdaControlsFeature;
import me.lambdaurora.lambdacontrols.client.compat.LambdaControlsCompat; import me.lambdaurora.lambdacontrols.client.compat.LambdaControlsCompat;
import me.lambdaurora.lambdacontrols.client.controller.ButtonBinding; import me.lambdaurora.lambdacontrols.client.controller.ButtonBinding;
import me.lambdaurora.lambdacontrols.client.controller.Controller; import me.lambdaurora.lambdacontrols.client.controller.Controller;
import me.lambdaurora.lambdacontrols.client.controller.InputManager;
import me.lambdaurora.lambdacontrols.client.gui.LambdaControlsHud; import me.lambdaurora.lambdacontrols.client.gui.LambdaControlsHud;
import me.lambdaurora.lambdacontrols.client.gui.TouchscreenOverlay; import me.lambdaurora.lambdacontrols.client.gui.TouchscreenOverlay;
import me.lambdaurora.spruceui.event.OpenScreenCallback; import me.lambdaurora.spruceui.event.OpenScreenCallback;
import me.lambdaurora.spruceui.hud.HudManager; import me.lambdaurora.spruceui.hud.HudManager;
import net.fabricmc.api.ClientModInitializer; import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.fabric.api.client.keybinding.FabricKeyBinding; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
import net.fabricmc.fabric.api.client.keybinding.KeyBindingRegistry; import net.fabricmc.fabric.api.client.keybinding.KeyBindingRegistry;
import net.fabricmc.fabric.api.event.client.ClientTickCallback; import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper;
import net.fabricmc.fabric.api.network.ClientSidePacketRegistry; import net.fabricmc.fabric.api.network.ClientSidePacketRegistry;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.client.font.TextRenderer; import net.minecraft.client.options.KeyBinding;
import net.minecraft.client.gui.DrawableHelper;
import net.minecraft.client.resource.language.I18n;
import net.minecraft.client.toast.SystemToast; import net.minecraft.client.toast.SystemToast;
import net.minecraft.client.util.InputUtil; import net.minecraft.client.util.InputUtil;
import net.minecraft.text.LiteralText; import net.minecraft.text.LiteralText;
import net.minecraft.text.TranslatableText; import net.minecraft.text.TranslatableText;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import org.aperlambda.lambdacommon.utils.Pair;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.lwjgl.glfw.GLFW; import org.lwjgl.glfw.GLFW;
@@ -43,22 +40,23 @@ import org.lwjgl.glfw.GLFW;
* Represents the LambdaControls client mod. * Represents the LambdaControls client mod.
* *
* @author LambdAurora * @author LambdAurora
* @version 1.1.0 * @version 1.3.0
* @since 1.1.0 * @since 1.1.0
*/ */
public class LambdaControlsClient extends LambdaControls implements ClientModInitializer public class LambdaControlsClient extends LambdaControls implements ClientModInitializer
{ {
private static LambdaControlsClient INSTANCE; private static LambdaControlsClient INSTANCE;
public static final FabricKeyBinding BINDING_LOOK_UP = FabricKeyBinding.Builder.create(new Identifier(LambdaControlsConstants.NAMESPACE, "look_up"), public static final KeyBinding BINDING_LOOK_UP = InputManager.makeKeyBinding(new Identifier(LambdaControlsConstants.NAMESPACE, "look_up"),
InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_KP_8, "key.categories.movement").build(); InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_KP_8, "key.categories.movement");
public static final FabricKeyBinding BINDING_LOOK_RIGHT = FabricKeyBinding.Builder.create(new Identifier(LambdaControlsConstants.NAMESPACE, "look_right"), public static final KeyBinding BINDING_LOOK_RIGHT = InputManager.makeKeyBinding(new Identifier(LambdaControlsConstants.NAMESPACE, "look_right"),
InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_KP_6, "key.categories.movement").build(); InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_KP_6, "key.categories.movement");
public static final FabricKeyBinding BINDING_LOOK_DOWN = FabricKeyBinding.Builder.create(new Identifier(LambdaControlsConstants.NAMESPACE, "look_down"), public static final KeyBinding BINDING_LOOK_DOWN = InputManager.makeKeyBinding(new Identifier(LambdaControlsConstants.NAMESPACE, "look_down"),
InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_KP_2, "key.categories.movement").build(); InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_KP_2, "key.categories.movement");
public static final FabricKeyBinding BINDING_LOOK_LEFT = FabricKeyBinding.Builder.create(new Identifier(LambdaControlsConstants.NAMESPACE, "look_left"), public static final KeyBinding BINDING_LOOK_LEFT = InputManager.makeKeyBinding(new Identifier(LambdaControlsConstants.NAMESPACE, "look_left"),
InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_KP_4, "key.categories.movement").build(); InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_KP_4, "key.categories.movement");
public static final Identifier CONTROLLER_BUTTONS = new Identifier(LambdaControlsConstants.NAMESPACE, "textures/gui/controller_buttons.png"); public static final Identifier CONTROLLER_BUTTONS = new Identifier(LambdaControlsConstants.NAMESPACE, "textures/gui/controller_buttons.png");
public static final Identifier CONTROLLER_AXIS = new Identifier(LambdaControlsConstants.NAMESPACE, "textures/gui/controller_axis.png"); public static final Identifier CONTROLLER_AXIS = new Identifier(LambdaControlsConstants.NAMESPACE, "textures/gui/controller_axis.png");
public static final Identifier CURSOR_TEXTURE = new Identifier(LambdaControlsConstants.NAMESPACE, "textures/gui/cursor.png");
public final LambdaControlsConfig config = new LambdaControlsConfig(this); public final LambdaControlsConfig config = new LambdaControlsConfig(this);
public final LambdaInput input = new LambdaInput(this); public final LambdaInput input = new LambdaInput(this);
private LambdaControlsHud hud; private LambdaControlsHud hud;
@@ -68,10 +66,10 @@ public class LambdaControlsClient extends LambdaControls implements ClientModIni
public void onInitializeClient() public void onInitializeClient()
{ {
INSTANCE = this; INSTANCE = this;
KeyBindingRegistry.INSTANCE.register(BINDING_LOOK_UP); KeyBindingHelper.registerKeyBinding(BINDING_LOOK_UP);
KeyBindingRegistry.INSTANCE.register(BINDING_LOOK_RIGHT); KeyBindingHelper.registerKeyBinding(BINDING_LOOK_RIGHT);
KeyBindingRegistry.INSTANCE.register(BINDING_LOOK_DOWN); KeyBindingHelper.registerKeyBinding(BINDING_LOOK_DOWN);
KeyBindingRegistry.INSTANCE.register(BINDING_LOOK_LEFT); KeyBindingHelper.registerKeyBinding(BINDING_LOOK_LEFT);
ClientSidePacketRegistry.INSTANCE.register(CONTROLS_MODE_CHANNEL, (context, attachedData) -> context.getTaskQueue() ClientSidePacketRegistry.INSTANCE.register(CONTROLS_MODE_CHANNEL, (context, attachedData) -> context.getTaskQueue()
.execute(() -> ClientSidePacketRegistry.INSTANCE.sendToServer(CONTROLS_MODE_CHANNEL, this.makeControlsModeBuffer(this.config.getControlsMode())))); .execute(() -> ClientSidePacketRegistry.INSTANCE.sendToServer(CONTROLS_MODE_CHANNEL, this.makeControlsModeBuffer(this.config.getControlsMode()))));
@@ -81,7 +79,7 @@ public class LambdaControlsClient extends LambdaControls implements ClientModIni
LambdaControlsFeature.fromName(name).ifPresent(feature -> context.getTaskQueue().execute(() -> feature.setAllowed(allowed))); LambdaControlsFeature.fromName(name).ifPresent(feature -> context.getTaskQueue().execute(() -> feature.setAllowed(allowed)));
}); });
ClientTickCallback.EVENT.register(this::onTick); ClientTickEvents.END_CLIENT_TICK.register(this::onTick);
OpenScreenCallback.EVENT.register((client, screen) -> { OpenScreenCallback.EVENT.register((client, screen) -> {
if (screen == null && this.config.getControlsMode() == ControlsMode.TOUCHSCREEN) { if (screen == null && this.config.getControlsMode() == ControlsMode.TOUCHSCREEN) {
@@ -136,7 +134,7 @@ public class LambdaControlsClient extends LambdaControls implements ClientModIni
public void onRender(MinecraftClient client) public void onRender(MinecraftClient client)
{ {
this.input.onRender(client); this.input.onRender(client.getTickDelta(), client);
} }
/** /**
@@ -186,141 +184,4 @@ public class LambdaControlsClient extends LambdaControls implements ClientModIni
{ {
return INSTANCE; return INSTANCE;
} }
public static Pair<Integer, Integer> drawButton(int x, int y, @NotNull ButtonBinding button, @NotNull MinecraftClient client)
{
return drawButton(x, y, button.getButton(), client);
}
public static Pair<Integer, Integer> drawButton(int x, int y, int[] buttons, @NotNull MinecraftClient client)
{
int height = 0;
int length = 0;
int currentX = x;
for (int i = 0; i < buttons.length; i++) {
int btn = buttons[i];
Pair<Integer, Integer> size = drawButton(currentX, y, btn, client);
if (size.key > height)
height = size.key;
length += size.key;
if (i + 1 < buttons.length) {
length += 2;
currentX = x + length;
}
}
return Pair.of(length, height);
}
@SuppressWarnings("deprecated")
public static Pair<Integer, Integer> drawButton(int x, int y, int button, @NotNull MinecraftClient client)
{
boolean second = false;
if (button == -1)
return Pair.of(0, 0);
else if (button >= 500) {
button -= 1000;
second = true;
}
int controllerType = get().config.getControllerType().getId();
boolean axis = false;
int buttonOffset = button * 15;
switch (button) {
case GLFW.GLFW_GAMEPAD_BUTTON_LEFT_BUMPER:
buttonOffset = 7 * 15;
break;
case GLFW.GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER:
buttonOffset = 8 * 15;
break;
case GLFW.GLFW_GAMEPAD_BUTTON_BACK:
buttonOffset = 4 * 15;
break;
case GLFW.GLFW_GAMEPAD_BUTTON_START:
buttonOffset = 6 * 15;
break;
case GLFW.GLFW_GAMEPAD_BUTTON_GUIDE:
buttonOffset = 5 * 15;
break;
case GLFW.GLFW_GAMEPAD_BUTTON_LEFT_THUMB:
buttonOffset = 15 * 15;
break;
case GLFW.GLFW_GAMEPAD_BUTTON_RIGHT_THUMB:
buttonOffset = 16 * 15;
break;
case GLFW.GLFW_GAMEPAD_AXIS_LEFT_X + 100:
buttonOffset = 0;
axis = true;
break;
case GLFW.GLFW_GAMEPAD_AXIS_LEFT_Y + 100:
buttonOffset = 18;
axis = true;
break;
case GLFW.GLFW_GAMEPAD_AXIS_RIGHT_X + 100:
buttonOffset = 2 * 18;
axis = true;
break;
case GLFW.GLFW_GAMEPAD_AXIS_RIGHT_Y + 100:
buttonOffset = 3 * 18;
axis = true;
break;
case GLFW.GLFW_GAMEPAD_AXIS_LEFT_X + 200:
buttonOffset = 4 * 18;
axis = true;
break;
case GLFW.GLFW_GAMEPAD_AXIS_LEFT_Y + 200:
buttonOffset = 5 * 18;
axis = true;
break;
case GLFW.GLFW_GAMEPAD_AXIS_RIGHT_X + 200:
buttonOffset = 6 * 18;
axis = true;
break;
case GLFW.GLFW_GAMEPAD_AXIS_RIGHT_Y + 200:
buttonOffset = 7 * 18;
axis = true;
break;
case GLFW.GLFW_GAMEPAD_AXIS_LEFT_TRIGGER + 100:
case GLFW.GLFW_GAMEPAD_AXIS_LEFT_TRIGGER + 200:
buttonOffset = 9 * 15;
break;
case GLFW.GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER + 100:
case GLFW.GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER + 200:
buttonOffset = 10 * 15;
break;
}
client.getTextureManager().bindTexture(axis ? LambdaControlsClient.CONTROLLER_AXIS : LambdaControlsClient.CONTROLLER_BUTTONS);
GlStateManager.disableDepthTest();
GlStateManager.color4f(1.0F, second ? 0.0F : 1.0F, 1.0F, 1.0F);
DrawableHelper.blit(x, y, (float) buttonOffset, (float) (controllerType * (axis ? 18 : 15)), axis ? 18 : 15, axis ? 18 : 15, 256, 256);
GlStateManager.enableDepthTest();
return axis ? Pair.of(18, 18) : Pair.of(15, 15);
}
public static int drawButtonTip(int x, int y, @NotNull ButtonBinding button, boolean display, @NotNull MinecraftClient client)
{
return drawButtonTip(x, y, button.getButton(), button.getTranslationKey(), display, client);
}
public static int drawButtonTip(int x, int y, int[] button, @NotNull String action, boolean display, @NotNull MinecraftClient client)
{
if (display) {
int buttonWidth = drawButton(x, y, button, client).key;
String translatedAction = I18n.translate(action);
int textY = (15 - client.textRenderer.fontHeight) / 2;
client.textRenderer.drawWithShadow(translatedAction, (float) (x + buttonWidth + 5), (float) (y + textY), 14737632);
return getButtonTipWidth(translatedAction, client.textRenderer);
}
return -10;
}
private static int getButtonTipWidth(@NotNull String action, @NotNull TextRenderer textRenderer)
{
return 15 + 5 + textRenderer.getStringWidth(action);
}
} }

View File

@@ -34,21 +34,25 @@ import static org.lwjgl.glfw.GLFW.GLFW_GAMEPAD_AXIS_LEFT_Y;
public class LambdaControlsConfig public class LambdaControlsConfig
{ {
// General // General
private static final ControlsMode DEFAULT_CONTROLS_MODE = ControlsMode.DEFAULT; private static final ControlsMode DEFAULT_CONTROLS_MODE = ControlsMode.DEFAULT;
private static final boolean DEFAULT_AUTO_SWITCH_MODE = false; private static final boolean DEFAULT_AUTO_SWITCH_MODE = false;
// HUD // HUD
private static final boolean DEFAULT_HUD_ENABLE = true; private static final boolean DEFAULT_HUD_ENABLE = true;
private static final HudSide DEFAULT_HUD_SIDE = HudSide.LEFT; private static final HudSide DEFAULT_HUD_SIDE = HudSide.LEFT;
// Gameplay // Gameplay
private static final boolean DEFAULT_FRONT_BLOCK_PLACING = false; private static final boolean DEFAULT_FAST_BLOCK_INTERACTION = true;
private static final boolean DEFAULT_FLY_DRIFTING = false; private static final boolean DEFAULT_FLY_DRIFTING = false;
private static final boolean DEFAULT_FLY_VERTICAL_DRIFTING = true; private static final boolean DEFAULT_FLY_VERTICAL_DRIFTING = true;
private static final boolean DEFAULT_FRONT_BLOCK_PLACING = false;
private static final boolean DEFAULT_FRONT_BLOCK_OUTLINE = true;
// Controller // Controller
private static final ControllerType DEFAULT_CONTROLLER_TYPE = ControllerType.DEFAULT; private static final ControllerType DEFAULT_CONTROLLER_TYPE = ControllerType.DEFAULT;
private static final double DEFAULT_DEAD_ZONE = 0.25; private static final double DEFAULT_DEAD_ZONE = 0.25;
private static final double DEFAULT_ROTATION_SPEED = 40.0; private static final double DEFAULT_ROTATION_SPEED = 40.0;
private static final double DEFAULT_MOUSE_SPEED = 25.0; private static final double DEFAULT_MOUSE_SPEED = 25.0;
private static final boolean DEFAULT_UNFOCUSED_INPUT = false; private static final boolean DEFAULT_UNFOCUSED_INPUT = false;
private static final boolean DEFAULT_VIRTUAL_MOUSE = false;
private static final VirtualMouseSkin DEFAULT_VIRTUAL_MOUSE_SKIN = VirtualMouseSkin.DEFAULT_LIGHT;
private static final Pattern BUTTON_BINDING_PATTERN = Pattern.compile("(-?\\d+)\\+?"); private static final Pattern BUTTON_BINDING_PATTERN = Pattern.compile("(-?\\d+)\\+?");
@@ -56,14 +60,19 @@ public class LambdaControlsConfig
private final LambdaControlsClient mod; private final LambdaControlsClient mod;
private ControlsMode controlsMode; private ControlsMode controlsMode;
private ControllerType controllerType; private ControllerType controllerType;
// HUD settings. // Gameplay.
private boolean hudEnable; private boolean shouldRenderFrontBlockOutline;
private HudSide hudSide; private int[] frontBlockOutlineColor;
// Controller settings // Controller settings
private double deadZone; private double deadZone;
private double rotationSpeed; private double rotationSpeed;
private double mouseSpeed; private double mouseSpeed;
private boolean unfocusedInput; private boolean unfocusedInput;
private boolean virtualMouse;
private VirtualMouseSkin virtualMouseSkin;
// HUD settings.
private boolean hudEnable;
private HudSide hudSide;
public LambdaControlsConfig(@NotNull LambdaControlsClient mod) public LambdaControlsConfig(@NotNull LambdaControlsClient mod)
{ {
@@ -83,13 +92,18 @@ public class LambdaControlsConfig
this.hudEnable = this.config.getOrElse("hud.enable", DEFAULT_HUD_ENABLE); this.hudEnable = this.config.getOrElse("hud.enable", DEFAULT_HUD_ENABLE);
this.hudSide = HudSide.byId(this.config.getOrElse("hud.side", DEFAULT_HUD_SIDE.getName())).orElse(DEFAULT_HUD_SIDE); this.hudSide = HudSide.byId(this.config.getOrElse("hud.side", DEFAULT_HUD_SIDE.getName())).orElse(DEFAULT_HUD_SIDE);
// Gameplay // Gameplay
LambdaControlsFeature.FRONT_BLOCK_PLACING.setEnabled(this.config.getOrElse("gameplay.front_block_placing", DEFAULT_FRONT_BLOCK_PLACING)); LambdaControlsFeature.FAST_BLOCK_PLACING.setEnabled(this.config.getOrElse("gameplay.fast_block_placing", DEFAULT_FAST_BLOCK_INTERACTION));
LambdaControlsFeature.FRONT_BLOCK_PLACING.setEnabled(this.config.getOrElse("gameplay.front_block_placing.enabled", DEFAULT_FRONT_BLOCK_PLACING));
this.shouldRenderFrontBlockOutline = this.config.getOrElse("gameplay.front_block_placing.outline", DEFAULT_FRONT_BLOCK_OUTLINE);
this.frontBlockOutlineColor = this.config.getOptional("gameplay.front_block_placing.outline_color").map(hex -> parseColor((String) hex)).orElse(new int[]{255, 255, 255, 102});
// Controller settings. // Controller settings.
this.controllerType = ControllerType.byId(this.config.getOrElse("controller.type", DEFAULT_CONTROLLER_TYPE.getName())).orElse(DEFAULT_CONTROLLER_TYPE); this.controllerType = ControllerType.byId(this.config.getOrElse("controller.type", DEFAULT_CONTROLLER_TYPE.getName())).orElse(DEFAULT_CONTROLLER_TYPE);
this.deadZone = this.config.getOrElse("controller.dead_zone", DEFAULT_DEAD_ZONE); this.deadZone = this.config.getOrElse("controller.dead_zone", DEFAULT_DEAD_ZONE);
this.rotationSpeed = this.config.getOrElse("controller.rotation_speed", DEFAULT_ROTATION_SPEED); this.rotationSpeed = this.config.getOrElse("controller.rotation_speed", DEFAULT_ROTATION_SPEED);
this.mouseSpeed = this.config.getOrElse("controller.mouse_speed", DEFAULT_MOUSE_SPEED); this.mouseSpeed = this.config.getOrElse("controller.mouse_speed", DEFAULT_MOUSE_SPEED);
this.unfocusedInput = this.config.getOrElse("controller.unfocused_input", DEFAULT_UNFOCUSED_INPUT); this.unfocusedInput = this.config.getOrElse("controller.unfocused_input", DEFAULT_UNFOCUSED_INPUT);
this.virtualMouse = this.config.getOrElse("controller.virtual_mouse", DEFAULT_VIRTUAL_MOUSE);
this.virtualMouseSkin = VirtualMouseSkin.byId(this.config.getOrElse("controller.virtual_mouse_skin", DEFAULT_VIRTUAL_MOUSE_SKIN.getName())).orElse(DEFAULT_VIRTUAL_MOUSE_SKIN);
// Controller controls. // Controller controls.
InputManager.loadButtonBindings(this); InputManager.loadButtonBindings(this);
} }
@@ -103,6 +117,7 @@ public class LambdaControlsConfig
this.config.set("controller.rotation_speed", this.rotationSpeed); this.config.set("controller.rotation_speed", this.rotationSpeed);
this.config.set("controller.mouse_speed", this.mouseSpeed); this.config.set("controller.mouse_speed", this.mouseSpeed);
this.config.set("controller.unfocused_input", this.unfocusedInput); this.config.set("controller.unfocused_input", this.unfocusedInput);
this.config.set("controller.virtual_mouse", this.virtualMouse);
this.config.save(); this.config.save();
this.mod.log("Configuration saved."); this.mod.log("Configuration saved.");
} }
@@ -117,6 +132,24 @@ public class LambdaControlsConfig
this.config.set(path, String.valueOf(raw)); this.config.set(path, String.valueOf(raw));
} }
}); });
// This shouldn't happen if the configuration is new.
if (!this.config.contains("gameplay.front_block_placing.enabled") && this.config.contains("gameplay.front_block_placing")) {
this.config.remove("gameplay.front_block_placing");
this.config.set("gameplay.front_block_placing.enabled", DEFAULT_FRONT_BLOCK_PLACING);
}
this.renamed("controller.controls.tab_left", "controller.controls.tab_back");
this.renamed("controller.controls.tab_right", "controller.controls.tab_next");
}
private void renamed(String oldPath, String newPath)
{
if (!this.config.contains(oldPath))
return;
Object raw = this.config.getRaw(oldPath);
this.config.remove(oldPath);
this.config.set(newPath, raw);
} }
/** /**
@@ -127,19 +160,23 @@ public class LambdaControlsConfig
// General // General
this.setControlsMode(DEFAULT_CONTROLS_MODE); this.setControlsMode(DEFAULT_CONTROLS_MODE);
this.setAutoSwitchMode(DEFAULT_AUTO_SWITCH_MODE); this.setAutoSwitchMode(DEFAULT_AUTO_SWITCH_MODE);
// HUD
this.setHudEnabled(DEFAULT_HUD_ENABLE);
this.setHudSide(DEFAULT_HUD_SIDE);
// Gameplay // Gameplay
this.setFrontBlockPlacing(DEFAULT_FRONT_BLOCK_PLACING); this.setFastBlockPlacing(DEFAULT_FAST_BLOCK_INTERACTION);
this.setFlyDrifting(DEFAULT_FLY_DRIFTING); this.setFlyDrifting(DEFAULT_FLY_DRIFTING);
this.setFlyVerticalDrifting(DEFAULT_FLY_VERTICAL_DRIFTING); this.setFlyVerticalDrifting(DEFAULT_FLY_VERTICAL_DRIFTING);
this.setFrontBlockPlacing(DEFAULT_FRONT_BLOCK_PLACING);
this.setRenderFrontBlockOutline(DEFAULT_FRONT_BLOCK_OUTLINE);
// Controller // Controller
this.setControllerType(DEFAULT_CONTROLLER_TYPE); this.setControllerType(DEFAULT_CONTROLLER_TYPE);
this.setDeadZone(DEFAULT_DEAD_ZONE); this.setDeadZone(DEFAULT_DEAD_ZONE);
this.setRotationSpeed(DEFAULT_ROTATION_SPEED); this.setRotationSpeed(DEFAULT_ROTATION_SPEED);
this.setMouseSpeed(DEFAULT_MOUSE_SPEED); this.setMouseSpeed(DEFAULT_MOUSE_SPEED);
this.setUnfocusedInput(DEFAULT_UNFOCUSED_INPUT); this.setUnfocusedInput(DEFAULT_UNFOCUSED_INPUT);
this.setVirtualMouse(DEFAULT_VIRTUAL_MOUSE);
this.setVirtualMouseSkin(DEFAULT_VIRTUAL_MOUSE_SKIN);
// HUD
this.setHudEnabled(DEFAULT_HUD_ENABLE);
this.setHudSide(DEFAULT_HUD_SIDE);
// Collect prevents concurrent modification. // Collect prevents concurrent modification.
InputManager.streamBindings().collect(Collectors.toList()).forEach(binding -> this.setButtonBinding(binding, binding.getDefaultButton())); InputManager.streamBindings().collect(Collectors.toList()).forEach(binding -> this.setButtonBinding(binding, binding.getDefaultButton()));
@@ -237,24 +274,24 @@ public class LambdaControlsConfig
*/ */
/** /**
* Returns whether front block placing is enabled or not. * Gets whether fast block placing is enabled or not.
* *
* @return True if front block placing is enabled, else false. * @return True if fast block placing is enabled, else false.
*/ */
public boolean hasFrontBlockPlacing() public boolean hasFastBlockPlacing()
{ {
return LambdaControlsFeature.FRONT_BLOCK_PLACING.isEnabled(); return LambdaControlsFeature.FAST_BLOCK_PLACING.isEnabled();
} }
/** /**
* Sets whether front block placing is enabled or not. * Sets whether fast block placing is enabled or not.
* *
* @param enable True if front block placing is enabled, else false. * @param enable True if fast block placing is enabled, else false.
*/ */
public void setFrontBlockPlacing(boolean enable) public void setFastBlockPlacing(boolean enable)
{ {
LambdaControlsFeature.FRONT_BLOCK_PLACING.setEnabled(enable); LambdaControlsFeature.FAST_BLOCK_PLACING.setEnabled(enable);
this.config.set("gameplay.front_block_placing", enable); this.config.set("gameplay.fast_block_placing", enable);
} }
/** /**
@@ -297,6 +334,59 @@ public class LambdaControlsConfig
this.config.set("gameplay.fly.vertical_drifting", flyDrifting); this.config.set("gameplay.fly.vertical_drifting", flyDrifting);
} }
/**
* Returns whether front block placing is enabled or not.
*
* @return True if front block placing is enabled, else false.
*/
public boolean hasFrontBlockPlacing()
{
return LambdaControlsFeature.FRONT_BLOCK_PLACING.isEnabled();
}
/**
* Sets whether front block placing is enabled or not.
*
* @param enable True if front block placing is enabled, else false.
*/
public void setFrontBlockPlacing(boolean enable)
{
LambdaControlsFeature.FRONT_BLOCK_PLACING.setEnabled(enable);
this.config.set("gameplay.front_block_placing.enabled", enable);
}
/**
* Returns whether front block placing outline is enabled or not.
*
* @return True if front block placing outline is enabled, else false.
*/
public boolean shouldRenderFrontBlockOutline()
{
return this.shouldRenderFrontBlockOutline;
}
/**
* Sets whether front block placing outline is enabled or not.
*
* @param render True if front block placing outline is enabled, else false.
*/
public void setRenderFrontBlockOutline(boolean render)
{
this.config.set("gameplay.front_block_placing.outline", this.shouldRenderFrontBlockOutline = render);
}
/**
* Returns the front block placing outline color as an integer array.
* <p>
* The integer array has 4 elements: red, green, blue and alpha.
*
* @return The color as a RGBA integer array.
*/
public int[] getFrontBlockOutlineColor()
{
return this.frontBlockOutlineColor;
}
/* /*
Controller settings Controller settings
*/ */
@@ -496,6 +586,47 @@ public class LambdaControlsConfig
this.unfocusedInput = unfocusedInput; this.unfocusedInput = unfocusedInput;
} }
/**
* Returns whether the mouse is virtual or not.
*
* @return True if the mouse is virtual, else false.
*/
public boolean hasVirtualMouse()
{
return this.virtualMouse;
}
/**
* Sets whether the mouse is virtual or not.
*
* @param virtualMouse True if the mouse is virtual, else false.
*/
public void setVirtualMouse(boolean virtualMouse)
{
this.virtualMouse = virtualMouse;
}
/**
* Gets the virtual mouse skin.
*
* @return The virtual mouse skin.
*/
public VirtualMouseSkin getVirtualMouseSkin()
{
return this.virtualMouseSkin;
}
/**
* Sets the virtual mouse skin.
*
* @param skin The virtual mouse skin.
*/
public void setVirtualMouseSkin(VirtualMouseSkin skin)
{
this.virtualMouseSkin = skin;
this.config.set("controller.virtual_mouse_skin", skin.getName());
}
/** /**
* Gets the right X axis sign. * Gets the right X axis sign.
* *
@@ -612,4 +743,32 @@ public class LambdaControlsConfig
{ {
return axis == GLFW_GAMEPAD_AXIS_LEFT_Y || axis == GLFW_GAMEPAD_AXIS_LEFT_X; return axis == GLFW_GAMEPAD_AXIS_LEFT_Y || axis == GLFW_GAMEPAD_AXIS_LEFT_X;
} }
/**
* Parses a color from a hexadecimal color string.
*
* @param hex The hexadecimal color.
* @return The color instance, null if invalid.
*/
private static int[] parseColor(String hex)
{
hex = hex.replace("#", "");
switch (hex.length()) {
case 6:
return new int[]{
Integer.valueOf(hex.substring(0, 2), 16),
Integer.valueOf(hex.substring(2, 4), 16),
Integer.valueOf(hex.substring(4, 6), 16),
255
};
case 8:
return new int[]{
Integer.valueOf(hex.substring(0, 2), 16),
Integer.valueOf(hex.substring(2, 4), 16),
Integer.valueOf(hex.substring(4, 6), 16),
Integer.valueOf(hex.substring(6, 8), 16)
};
}
return null;
}
} }

View File

@@ -9,32 +9,23 @@
package me.lambdaurora.lambdacontrols.client; package me.lambdaurora.lambdacontrols.client;
import io.github.prospector.modmenu.api.ConfigScreenFactory;
import io.github.prospector.modmenu.api.ModMenuApi; import io.github.prospector.modmenu.api.ModMenuApi;
import me.lambdaurora.lambdacontrols.LambdaControlsConstants; import me.lambdaurora.lambdacontrols.LambdaControlsConstants;
import me.lambdaurora.lambdacontrols.client.gui.LambdaControlsSettingsScreen; import me.lambdaurora.lambdacontrols.client.gui.LambdaControlsSettingsScreen;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.Screen;
import java.util.function.Function;
/** /**
* Represents the API implementation of ModMenu for LambdaControls. * Represents the API implementation of ModMenu for LambdaControls.
* *
* @author LambdAurora * @author LambdAurora
* @version 1.1.0 * @version 1.3.0
* @since 1.1.0 * @since 1.1.0
*/ */
public class LambdaControlsModMenu implements ModMenuApi public class LambdaControlsModMenu implements ModMenuApi
{ {
@Override @Override
public String getModId() public ConfigScreenFactory<?> getModConfigScreenFactory()
{ {
return LambdaControlsConstants.NAMESPACE; return parent -> new LambdaControlsSettingsScreen(parent, false);
}
@Override
public Function<Screen, ? extends Screen> getConfigScreenFactory()
{
return screen -> new LambdaControlsSettingsScreen(screen, MinecraftClient.getInstance().options, false);
} }
} }

View File

@@ -9,30 +9,47 @@
package me.lambdaurora.lambdacontrols.client; package me.lambdaurora.lambdacontrols.client;
import me.lambdaurora.lambdacontrols.LambdaControlsFeature;
import me.lambdaurora.lambdacontrols.client.compat.LambdaControlsCompat;
import me.lambdaurora.lambdacontrols.client.controller.ButtonBinding; import me.lambdaurora.lambdacontrols.client.controller.ButtonBinding;
import me.lambdaurora.lambdacontrols.client.controller.Controller; import me.lambdaurora.lambdacontrols.client.controller.Controller;
import me.lambdaurora.lambdacontrols.client.controller.InputManager; import me.lambdaurora.lambdacontrols.client.controller.InputManager;
import me.lambdaurora.lambdacontrols.client.gui.ControllerControlsScreen; import me.lambdaurora.lambdacontrols.client.gui.ControllerControlsScreen;
import me.lambdaurora.lambdacontrols.client.gui.TouchscreenOverlay; import me.lambdaurora.lambdacontrols.client.gui.TouchscreenOverlay;
import me.lambdaurora.lambdacontrols.client.mixin.AdvancementsScreenAccessor;
import me.lambdaurora.lambdacontrols.client.mixin.CreativeInventoryScreenAccessor; import me.lambdaurora.lambdacontrols.client.mixin.CreativeInventoryScreenAccessor;
import me.lambdaurora.lambdacontrols.client.mixin.EntryListWidgetAccessor; import me.lambdaurora.lambdacontrols.client.mixin.EntryListWidgetAccessor;
import me.lambdaurora.lambdacontrols.client.util.ContainerScreenAccessor; import me.lambdaurora.lambdacontrols.client.util.HandledScreenAccessor;
import me.lambdaurora.lambdacontrols.client.util.MouseAccessor;
import me.lambdaurora.spruceui.SpruceLabelWidget; import me.lambdaurora.spruceui.SpruceLabelWidget;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.FluidBlock;
import net.minecraft.block.SlabBlock;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.Element; import net.minecraft.client.gui.Element;
import net.minecraft.client.gui.ParentElement; import net.minecraft.client.gui.ParentElement;
import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.screen.advancement.AdvancementTab;
import net.minecraft.client.gui.screen.advancement.AdvancementsScreen; import net.minecraft.client.gui.screen.advancement.AdvancementsScreen;
import net.minecraft.client.gui.screen.ingame.ContainerScreen;
import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen; import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen;
import net.minecraft.client.gui.screen.ingame.HandledScreen;
import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen; import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen;
import net.minecraft.client.gui.screen.multiplayer.MultiplayerServerListWidget; import net.minecraft.client.gui.screen.multiplayer.MultiplayerServerListWidget;
import net.minecraft.client.gui.screen.world.WorldListWidget; import net.minecraft.client.gui.screen.world.WorldListWidget;
import net.minecraft.client.gui.widget.AbstractPressableButtonWidget; import net.minecraft.client.gui.widget.AbstractPressableButtonWidget;
import net.minecraft.client.gui.widget.AlwaysSelectedEntryListWidget; import net.minecraft.client.gui.widget.AlwaysSelectedEntryListWidget;
import net.minecraft.client.gui.widget.EntryListWidget;
import net.minecraft.client.gui.widget.SliderWidget; import net.minecraft.client.gui.widget.SliderWidget;
import net.minecraft.container.Slot; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.container.SlotActionType; import net.minecraft.item.BlockItem;
import net.minecraft.item.ItemStack;
import net.minecraft.screen.slot.Slot;
import net.minecraft.screen.slot.SlotActionType;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.hit.HitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.MathHelper;
import org.aperlambda.lambdacommon.utils.Pair; import org.aperlambda.lambdacommon.utils.Pair;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -55,27 +72,24 @@ import static org.lwjgl.glfw.GLFW.*;
* Represents the LambdaControls' input handler. * Represents the LambdaControls' input handler.
* *
* @author LambdAurora * @author LambdAurora
* @version 1.1.0 * @version 1.3.1
* @since 1.0.0 * @since 1.0.0
*/ */
public class LambdaInput public class LambdaInput
{ {
private static final Map<Integer, Integer> BUTTON_COOLDOWNS = new HashMap<>(); private static final Map<Integer, Integer> BUTTON_COOLDOWNS = new HashMap<>();
private final LambdaControlsConfig config; private final LambdaControlsConfig config;
// Cooldowns // Cooldowns
private int actionGuiCooldown = 0; private int actionGuiCooldown = 0;
private int ignoreNextA = 0; private boolean ignoreNextARelease = false;
// Sneak state. private double targetYaw = 0.0;
private double prevTargetYaw = 0.0; private double targetPitch = 0.0;
private double prevTargetPitch = 0.0; private float prevXAxis = 0.F;
private double targetYaw = 0.0; private float prevYAxis = 0.F;
private double targetPitch = 0.0; private int targetMouseX = 0;
private float prevXAxis = 0.F; private int targetMouseY = 0;
private float prevYAxis = 0.F; private float mouseSpeedX = 0.F;
private int targetMouseX = 0; private float mouseSpeedY = 0.F;
private int targetMouseY = 0;
private float mouseSpeedX = 0.F;
private float mouseSpeedY = 0.F;
public LambdaInput(@NotNull LambdaControlsClient mod) public LambdaInput(@NotNull LambdaControlsClient mod)
{ {
@@ -89,8 +103,8 @@ public class LambdaInput
*/ */
public void onTick(@NotNull MinecraftClient client) public void onTick(@NotNull MinecraftClient client)
{ {
this.prevTargetYaw = this.targetYaw; this.targetYaw = 0.F;
this.prevTargetPitch = this.targetPitch; this.targetPitch = 0.F;
// Handles the key bindings. // Handles the key bindings.
if (LambdaControlsClient.BINDING_LOOK_UP.isPressed()) { if (LambdaControlsClient.BINDING_LOOK_UP.isPressed()) {
@@ -142,9 +156,6 @@ public class LambdaInput
if (allowInput) if (allowInput)
InputManager.updateBindings(client); InputManager.updateBindings(client);
if (this.ignoreNextA > 0)
this.ignoreNextA--;
if (client.currentScreen instanceof ControllerControlsScreen && InputManager.STATES.entrySet().parallelStream().map(Map.Entry::getValue).allMatch(ButtonState::isUnpressed)) { if (client.currentScreen instanceof ControllerControlsScreen && InputManager.STATES.entrySet().parallelStream().map(Map.Entry::getValue).allMatch(ButtonState::isUnpressed)) {
ControllerControlsScreen screen = (ControllerControlsScreen) client.currentScreen; ControllerControlsScreen screen = (ControllerControlsScreen) client.currentScreen;
if (screen.focusedBinding != null && !screen.waiting) { if (screen.focusedBinding != null && !screen.waiting) {
@@ -175,20 +186,24 @@ public class LambdaInput
* *
* @param client The client instance. * @param client The client instance.
*/ */
public void onRender(@NotNull MinecraftClient client) public void onRender(float tickDelta, @NotNull MinecraftClient client)
{ {
if ((client.currentScreen == null || client.currentScreen instanceof TouchscreenOverlay) && if (!(client.currentScreen == null || client.currentScreen instanceof TouchscreenOverlay))
(this.prevTargetYaw != this.targetYaw || this.prevTargetPitch != this.targetPitch)) { return;
float deltaYaw = (float) ((this.targetYaw - client.player.prevYaw) * client.getTickDelta());
float deltaPitch = (float) ((this.targetPitch - client.player.prevPitch) * client.getTickDelta()); PlayerEntity player = client.player;
float rotationYaw = client.player.prevYaw + deltaYaw; if (player == null)
float rotationPitch = client.player.prevPitch + deltaPitch; return;
if (this.targetYaw != 0F || this.targetPitch != 0F) {
float rotationYaw = (float) (player.prevYaw + (this.targetYaw / 0.10) * tickDelta);
float rotationPitch = (float) (player.prevPitch + (this.targetPitch / 0.10) * tickDelta);
client.player.yaw = rotationYaw; client.player.yaw = rotationYaw;
client.player.pitch = MathHelper.clamp(rotationPitch, -90.F, 90.F); client.player.pitch = MathHelper.clamp(rotationPitch, -90.F, 90.F);
if (client.player.isRiding()) { if (client.player.isRiding()) {
client.player.getVehicle().copyPositionAndRotation(client.player); client.player.getVehicle().copyPositionAndRotation(client.player);
} }
client.getTutorialManager().onUpdateMouse(deltaPitch, deltaYaw); client.getTutorialManager().onUpdateMouse(this.targetPitch, this.targetYaw);
} }
} }
@@ -204,6 +219,9 @@ public class LambdaInput
if (client.currentScreen == null) { if (client.currentScreen == null) {
this.mouseSpeedX = this.mouseSpeedY = 0.0F; this.mouseSpeedX = this.mouseSpeedY = 0.0F;
INPUT_MANAGER.resetMousePosition(windowWidth, windowHeight); INPUT_MANAGER.resetMousePosition(windowWidth, windowHeight);
} else if (isScreenInteractive(client.currentScreen) && this.config.hasVirtualMouse()) {
((MouseAccessor) client.mouse).lambdacontrols_onCursorPos(client.getWindow().getHandle(), 0, 0);
INPUT_MANAGER.resetMouseTarget(client);
} }
} }
@@ -300,30 +318,12 @@ public class LambdaInput
} }
} }
if (client.currentScreen instanceof ContainerScreen && client.interactionManager != null && client.player != null) { if (this.handleInventory(client, button)) {
double x = client.mouse.getX() * (double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth(); this.ignoreNextARelease = true;
double y = client.mouse.getY() * (double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight(); return;
Slot slot = ((ContainerScreenAccessor) client.currentScreen).lambdacontrols_getSlotAt(x, y); }
SlotActionType slotAction = SlotActionType.PICKUP;
if (button == GLFW.GLFW_GAMEPAD_BUTTON_A && slot != null) { if (button == GLFW.GLFW_GAMEPAD_BUTTON_B) {
if (client.currentScreen instanceof CreativeInventoryScreen) {
if (((CreativeInventoryScreenAccessor) client.currentScreen).lambdacontrols_isCreativeInventorySlot(slot))
slotAction = SlotActionType.CLONE;
}
client.interactionManager.clickSlot(((ContainerScreen) client.currentScreen).getContainer().syncId, slot.id, GLFW.GLFW_MOUSE_BUTTON_1, slotAction, client.player);
this.actionGuiCooldown = 5;
return;
} else if (button == GLFW.GLFW_GAMEPAD_BUTTON_B) {
client.player.closeContainer();
return;
} else if (button == GLFW.GLFW_GAMEPAD_BUTTON_X && slot != null) {
client.interactionManager.clickSlot(((ContainerScreen) client.currentScreen).getContainer().syncId, slot.id, GLFW.GLFW_MOUSE_BUTTON_2, SlotActionType.PICKUP, client.player);
return;
} else if (button == GLFW.GLFW_GAMEPAD_BUTTON_Y && slot != null) {
client.interactionManager.clickSlot(((ContainerScreen) client.currentScreen).getContainer().syncId, slot.id, GLFW.GLFW_MOUSE_BUTTON_1, SlotActionType.QUICK_MOVE, client.player);
return;
}
} else if (button == GLFW.GLFW_GAMEPAD_BUTTON_B) {
if (client.currentScreen != null) { if (client.currentScreen != null) {
client.currentScreen.onClose(); client.currentScreen.onClose();
return; return;
@@ -331,18 +331,80 @@ public class LambdaInput
} }
} }
if (button == GLFW.GLFW_GAMEPAD_BUTTON_A && client.currentScreen != null && !isScreenInteractive(client.currentScreen) && this.actionGuiCooldown == 0 && this.ignoreNextA == 0) { if (button == GLFW.GLFW_GAMEPAD_BUTTON_A && client.currentScreen != null && !isScreenInteractive(client.currentScreen) && this.actionGuiCooldown == 0) {
double mouseX = client.mouse.getX() * (double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth(); if (!this.ignoreNextARelease) {
double mouseY = client.mouse.getY() * (double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight(); double mouseX = client.mouse.getX() * (double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth();
if (action == 0) { double mouseY = client.mouse.getY() * (double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight();
client.currentScreen.mouseClicked(mouseX, mouseY, GLFW.GLFW_MOUSE_BUTTON_1); if (action == 0) {
} else if (action == 1) { client.currentScreen.mouseClicked(mouseX, mouseY, GLFW.GLFW_MOUSE_BUTTON_1);
client.currentScreen.mouseReleased(mouseX, mouseY, GLFW.GLFW_MOUSE_BUTTON_1); } else if (action == 1) {
client.currentScreen.mouseReleased(mouseX, mouseY, GLFW.GLFW_MOUSE_BUTTON_1);
}
this.actionGuiCooldown = 5;
} else {
this.ignoreNextARelease = false;
} }
this.actionGuiCooldown = 5;
} }
} }
/**
* Handles inventory interaction.
*
* @param client The client instance.
* @param button The button pressed.
* @return True if an inventory interaction was done.
*/
private boolean handleInventory(@NotNull MinecraftClient client, int button)
{
if (!(client.currentScreen instanceof HandledScreen))
return false;
if (client.interactionManager == null || client.player == null)
return false;
if (button == GLFW.GLFW_GAMEPAD_BUTTON_B) {
client.player.closeHandledScreen();
return true;
}
double x = client.mouse.getX() * (double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth();
double y = client.mouse.getY() * (double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight();
HandledScreen screen = (HandledScreen) client.currentScreen;
HandledScreenAccessor accessor = (HandledScreenAccessor) screen;
Slot slot = ((HandledScreenAccessor) client.currentScreen).lambdacontrols_getSlotAt(x, y);
int slotId;
if (slot == null) {
if (client.player.inventory.getCursorStack().isEmpty())
return false;
slotId = accessor.lambdacontrols_isClickOutsideBounds(x, y, accessor.getX(), accessor.getY(), GLFW_MOUSE_BUTTON_1) ? -999 : -1;
} else {
slotId = slot.id;
}
SlotActionType actionType = SlotActionType.PICKUP;
int clickData = GLFW.GLFW_MOUSE_BUTTON_1;
switch (button) {
case GLFW_GAMEPAD_BUTTON_A:
if (screen instanceof CreativeInventoryScreen)
if (((CreativeInventoryScreenAccessor) screen).lambdacontrols_isCreativeInventorySlot(slot))
actionType = SlotActionType.CLONE;
break;
case GLFW.GLFW_GAMEPAD_BUTTON_X:
clickData = GLFW_MOUSE_BUTTON_2;
break;
case GLFW.GLFW_GAMEPAD_BUTTON_Y:
actionType = SlotActionType.QUICK_MOVE;
break;
default:
return false;
}
accessor.lambdacontrols_onMouseClick(slot, slotId, clickData, actionType);
return true;
}
private void handleAxe(@NotNull MinecraftClient client, int axis, float value, float absValue, int state) private void handleAxe(@NotNull MinecraftClient client, int axis, float value, float absValue, int state)
{ {
int asButtonState = value > 0.5F ? 1 : (value < -0.5F ? 2 : 0); int asButtonState = value > 0.5F ? 1 : (value < -0.5F ? 2 : 0);
@@ -381,6 +443,8 @@ public class LambdaInput
} }
} }
double deadZone = this.config.getDeadZone();
if (client.currentScreen instanceof ControllerControlsScreen) { if (client.currentScreen instanceof ControllerControlsScreen) {
ControllerControlsScreen screen = (ControllerControlsScreen) client.currentScreen; ControllerControlsScreen screen = (ControllerControlsScreen) client.currentScreen;
if (screen.focusedBinding != null) { if (screen.focusedBinding != null) {
@@ -397,11 +461,30 @@ public class LambdaInput
} }
return; return;
} }
} else if (client.currentScreen instanceof CreativeInventoryScreen) {
if (axis == GLFW_GAMEPAD_AXIS_RIGHT_Y) {
CreativeInventoryScreen screen = (CreativeInventoryScreen) client.currentScreen;
CreativeInventoryScreenAccessor accessor = (CreativeInventoryScreenAccessor) screen;
if (accessor.lambdacontrols_hasScrollbar() && absValue >= deadZone) {
screen.mouseScrolled(0.0, 0.0, -value);
}
return;
}
} else if (client.currentScreen instanceof AdvancementsScreen) {
if (axis == GLFW_GAMEPAD_AXIS_RIGHT_X || axis == GLFW_GAMEPAD_AXIS_RIGHT_Y) {
AdvancementsScreen screen = (AdvancementsScreen) client.currentScreen;
AdvancementsScreenAccessor accessor = (AdvancementsScreenAccessor) screen;
if (absValue >= deadZone) {
AdvancementTab tab = accessor.getSelectedTab();
tab.move(axis == GLFW_GAMEPAD_AXIS_RIGHT_X ? -value * 5.0 : 0.0, axis == GLFW_GAMEPAD_AXIS_RIGHT_Y ? -value * 5.0 : 0.0);
}
return;
}
} }
double deadZone = this.config.getDeadZone();
if (client.currentScreen == null) { if (client.currentScreen == null) {
// Handles the look direction. // Handles the look direction.
absValue -= this.config.getDeadZone();
this.handleLook(client, axis, (float) (absValue / (1.0 - this.config.getDeadZone())), state); this.handleLook(client, axis, (float) (absValue / (1.0 - this.config.getDeadZone())), state);
} else { } else {
boolean allowMouseControl = true; boolean allowMouseControl = true;
@@ -520,7 +603,7 @@ public class LambdaInput
this.actionGuiCooldown = 2; // Prevent to press too quickly the focused element, so we have to skip 5 ticks. this.actionGuiCooldown = 2; // Prevent to press too quickly the focused element, so we have to skip 5 ticks.
return false; return false;
} else if (element instanceof AlwaysSelectedEntryListWidget) { } else if (element instanceof AlwaysSelectedEntryListWidget) {
((EntryListWidgetAccessor) element).lambdacontrols_moveSelection(right ? 1 : -1); ((EntryListWidgetAccessor) element).lambdacontrols_moveSelection(right ? EntryListWidget.class_5403.field_25661 : EntryListWidget.class_5403.field_25662);
return false; return false;
} else if (element instanceof ParentElement) { } else if (element instanceof ParentElement) {
ParentElement entryList = (ParentElement) element; ParentElement entryList = (ParentElement) element;
@@ -535,7 +618,7 @@ public class LambdaInput
/** /**
* Handles the look direction input. * Handles the look direction input.
* *
* @param client The client isntance. * @param client The client instance.
* @param axis The axis to change. * @param axis The axis to change.
* @param value The value of the look. * @param value The value of the look.
* @param state The state. * @param state The state.
@@ -544,21 +627,19 @@ public class LambdaInput
{ {
// Handles the look direction. // Handles the look direction.
if (client.player != null) { if (client.player != null) {
double powValue = Math.pow(value, 4.0); double powValue = Math.pow(value, 2.0);
if (axis == GLFW_GAMEPAD_AXIS_RIGHT_Y) { if (axis == GLFW_GAMEPAD_AXIS_RIGHT_Y) {
if (state == 2) { if (state == 2) {
this.targetPitch = client.player.pitch - this.config.getRightYAxisSign() * (this.config.getRotationSpeed() * powValue) * 0.33D; this.targetPitch = -this.config.getRightYAxisSign() * (this.config.getRotationSpeed() * powValue) * 0.33D;
this.targetPitch = MathHelper.clamp(this.targetPitch, -90.0D, 90.0D);
} else if (state == 1) { } else if (state == 1) {
this.targetPitch = client.player.pitch + this.config.getRightYAxisSign() * (this.config.getRotationSpeed() * powValue) * 0.33D; this.targetPitch = this.config.getRightYAxisSign() * (this.config.getRotationSpeed() * powValue) * 0.33D;
this.targetPitch = MathHelper.clamp(this.targetPitch, -90.0D, 90.0D);
} }
} }
if (axis == GLFW_GAMEPAD_AXIS_RIGHT_X) { if (axis == GLFW_GAMEPAD_AXIS_RIGHT_X) {
if (state == 2) { if (state == 2) {
this.targetYaw = client.player.yaw - this.config.getRightXAxisSign() * (this.config.getRotationSpeed() * powValue) * 0.33D; this.targetYaw = -this.config.getRightXAxisSign() * (this.config.getRotationSpeed() * powValue) * 0.33D;
} else if (state == 1) { } else if (state == 1) {
this.targetYaw = client.player.yaw + this.config.getRightXAxisSign() * (this.config.getRotationSpeed() * powValue) * 0.33D; this.targetYaw = this.config.getRightXAxisSign() * (this.config.getRotationSpeed() * powValue) * 0.33D;
} }
} }
} }
@@ -578,28 +659,28 @@ public class LambdaInput
} }
} }
private static boolean isScreenInteractive(@NotNull Screen screen) public static boolean isScreenInteractive(@NotNull Screen screen)
{ {
return !(screen instanceof AdvancementsScreen || screen instanceof ContainerScreen); return !(screen instanceof AdvancementsScreen || screen instanceof HandledScreen || LambdaControlsCompat.requireMouseOnScreen(screen));
} }
// Inspired from https://github.com/MrCrayfish/Controllable/blob/1.14.X/src/main/java/com/mrcrayfish/controllable/client/ControllerInput.java#L686. // Inspired from https://github.com/MrCrayfish/Controllable/blob/1.14.X/src/main/java/com/mrcrayfish/controllable/client/ControllerInput.java#L686.
private void moveMouseToClosestSlot(@NotNull MinecraftClient client, @Nullable Screen screen) private void moveMouseToClosestSlot(@NotNull MinecraftClient client, @Nullable Screen screen)
{ {
// Makes the mouse attracted to slots. This helps with selecting items when using a controller. // Makes the mouse attracted to slots. This helps with selecting items when using a controller.
if (screen instanceof ContainerScreen) { if (screen instanceof HandledScreen) {
ContainerScreen inventoryScreen = (ContainerScreen) screen; HandledScreen inventoryScreen = (HandledScreen) screen;
ContainerScreenAccessor accessor = (ContainerScreenAccessor) inventoryScreen; HandledScreenAccessor accessor = (HandledScreenAccessor) inventoryScreen;
int guiLeft = accessor.lambdacontrols_getX(); int guiLeft = accessor.getX();
int guiTop = accessor.lambdacontrols_getY(); int guiTop = accessor.getY();
int mouseX = (int) (targetMouseX * (double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth()); int mouseX = (int) (targetMouseX * (double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth());
int mouseY = (int) (targetMouseY * (double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight()); int mouseY = (int) (targetMouseY * (double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight());
// Finds the closest slot in the GUI within 14 pixels. // Finds the closest slot in the GUI within 14 pixels.
Optional<Pair<Slot, Double>> closestSlot = inventoryScreen.getContainer().slots.parallelStream() Optional<Pair<Slot, Double>> closestSlot = inventoryScreen.getScreenHandler().slots.parallelStream()
.map(slot -> { .map(slot -> {
int x = guiLeft + slot.xPosition + 8; int x = guiLeft + slot.x + 8;
int y = guiTop + slot.yPosition + 8; int y = guiTop + slot.y + 8;
// Distance between the slot and the cursor. // Distance between the slot and the cursor.
double distance = Math.sqrt(Math.pow(x - mouseX, 2) + Math.pow(y - mouseY, 2)); double distance = Math.sqrt(Math.pow(x - mouseX, 2) + Math.pow(y - mouseY, 2));
@@ -610,8 +691,8 @@ public class LambdaInput
if (closestSlot.isPresent()) { if (closestSlot.isPresent()) {
Slot slot = closestSlot.get().key; Slot slot = closestSlot.get().key;
if (slot.hasStack() || !client.player.inventory.getMainHandStack().isEmpty()) { if (slot.hasStack() || !client.player.inventory.getMainHandStack().isEmpty()) {
int slotCenterXScaled = guiLeft + slot.xPosition + 8; int slotCenterXScaled = guiLeft + slot.x + 8;
int slotCenterYScaled = guiTop + slot.yPosition + 8; int slotCenterYScaled = guiTop + slot.y + 8;
int slotCenterX = (int) (slotCenterXScaled / ((double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth())); int slotCenterX = (int) (slotCenterXScaled / ((double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth()));
int slotCenterY = (int) (slotCenterYScaled / ((double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight())); int slotCenterY = (int) (slotCenterYScaled / ((double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight()));
double deltaX = slotCenterX - targetMouseX; double deltaX = slotCenterX - targetMouseX;
@@ -639,4 +720,71 @@ public class LambdaInput
this.mouseSpeedY = 0.F; this.mouseSpeedY = 0.F;
} }
} }
public static Direction getMoveDirection(@Nullable BlockPos lastPos, @NotNull BlockPos newPos)
{
if (lastPos == null)
return null;
BlockPos vector = newPos.subtract(lastPos);
if (vector.getX() > 0)
return Direction.EAST;
else if (vector.getX() < 0)
return Direction.WEST;
else if (vector.getZ() > 0)
return Direction.SOUTH;
else if (vector.getZ() < 0)
return Direction.NORTH;
else if (vector.getY() > 0)
return Direction.UP;
else if (vector.getY() < 0)
return Direction.DOWN;
return null;
}
/**
* Returns a nullable block hit result if front placing is possible.
*
* @param client The client instance.
* @return A block hit result if front placing is possible.
*/
public static @Nullable BlockHitResult tryFrontPlace(@NotNull MinecraftClient client)
{
if (!LambdaControlsFeature.FRONT_BLOCK_PLACING.isAvailable())
return null;
if (client.player != null && client.crosshairTarget != null && client.crosshairTarget.getType() == HitResult.Type.MISS && client.player.isOnGround() && client.player.pitch > 35.0F) {
if (client.player.isRiding())
return null;
BlockPos playerPos = client.player.getBlockPos().down();
BlockPos targetPos = new BlockPos(client.crosshairTarget.getPos()).subtract(playerPos);
BlockPos vector = new BlockPos(MathHelper.clamp(targetPos.getX(), -1, 1), 0, MathHelper.clamp(targetPos.getZ(), -1, 1));
BlockPos blockPos = playerPos.add(vector);
Direction direction = client.player.getHorizontalFacing();
BlockState state = client.world.getBlockState(blockPos);
if (!state.isAir())
return null;
BlockState adjacentBlockState = client.world.getBlockState(blockPos.offset(direction.getOpposite()));
if (adjacentBlockState.isAir() || adjacentBlockState.getBlock() instanceof FluidBlock || (vector.getX() == 0 && vector.getZ() == 0)) {
return null;
}
return new BlockHitResult(client.crosshairTarget.getPos(), direction, blockPos, false);
}
return null;
}
public static @NotNull BlockHitResult withSideForFrontPlace(@NotNull BlockHitResult result, @Nullable ItemStack stack)
{
if (stack == null || stack.isEmpty() || !(stack.getItem() instanceof BlockItem))
return result;
return withSideForFrontPlace(result, Block.getBlockFromItem(stack.getItem()));
}
public static @NotNull BlockHitResult withSideForFrontPlace(@NotNull BlockHitResult result, @NotNull Block block)
{
if (block instanceof SlabBlock)
result = result.withSide(Direction.DOWN);
return result;
}
} }

View File

@@ -0,0 +1,77 @@
/*
* Copyright © 2020 LambdAurora <aurora42lambda@gmail.com>
*
* This file is part of LambdaControls.
*
* Licensed under the MIT license. For more information,
* see the LICENSE file.
*/
package me.lambdaurora.lambdacontrols.client;
import net.minecraft.client.resource.language.I18n;
import org.aperlambda.lambdacommon.utils.Nameable;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
import java.util.Optional;
/**
* Represents the virtual mouse skins.
*
* @version 1.2.0
* @since 1.2.0
*/
public enum VirtualMouseSkin implements Nameable
{
DEFAULT_LIGHT("default_light"),
DEFAULT_DARK("default_dark"),
SECOND_LIGHT("second_light"),
SECOND_DARK("second_dark");
private String name;
VirtualMouseSkin(String name) {
this.name = name;
}
/**
* Returns the next virtual mouse skin available.
*
* @return The next available virtual mouse skin.
*/
public VirtualMouseSkin next()
{
VirtualMouseSkin[] v = values();
if (v.length == this.ordinal() + 1)
return v[0];
return v[this.ordinal() + 1];
}
/**
* Gets the translated name of this controller type.
*
* @return The translated name of this controller type.
*/
public String getTranslatedName()
{
return I18n.translate("lambdacontrols.virtual_mouse.skin." + this.getName());
}
@Override
public @NotNull String getName()
{
return this.name;
}
/**
* Gets the controller type from its identifier.
*
* @param id The identifier of the controller type.
* @return The controller type if found, else empty.
*/
public static Optional<VirtualMouseSkin> byId(@NotNull String id)
{
return Arrays.stream(values()).filter(mode -> mode.getName().equalsIgnoreCase(id)).findFirst();
}
}

View File

@@ -10,13 +10,14 @@
package me.lambdaurora.lambdacontrols.client.compat; package me.lambdaurora.lambdacontrols.client.compat;
import me.lambdaurora.lambdacontrols.client.LambdaControlsClient; import me.lambdaurora.lambdacontrols.client.LambdaControlsClient;
import net.minecraft.client.gui.screen.Screen;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
/** /**
* Represents a compatibility handler for a mod. * Represents a compatibility handler for a mod.
* *
* @author LambdAurora * @author LambdAurora
* @version 1.1.0 * @version 1.2.0
* @since 1.1.0 * @since 1.1.0
*/ */
public interface CompatHandler public interface CompatHandler
@@ -27,4 +28,15 @@ public interface CompatHandler
* @param mod This mod instance. * @param mod This mod instance.
*/ */
void handle(@NotNull LambdaControlsClient mod); void handle(@NotNull LambdaControlsClient mod);
/**
* Returns whether the mouse is required on the specified screen.
*
* @param screen The screen.
* @return True if the mouse is requried on the specified screen, else false.
*/
default boolean requireMouseOnScreen(Screen screen)
{
return false;
}
} }

View File

@@ -12,9 +12,13 @@ package me.lambdaurora.lambdacontrols.client.compat;
import me.lambdaurora.lambdacontrols.client.LambdaControlsClient; import me.lambdaurora.lambdacontrols.client.LambdaControlsClient;
import me.lambdaurora.lambdacontrols.client.controller.InputManager; import me.lambdaurora.lambdacontrols.client.controller.InputManager;
import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.client.gui.screen.Screen;
import org.aperlambda.lambdacommon.utils.LambdaReflection; import org.aperlambda.lambdacommon.utils.LambdaReflection;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
/** /**
* Represents a compatibility handler. * Represents a compatibility handler.
* *
@@ -24,6 +28,8 @@ import org.jetbrains.annotations.NotNull;
*/ */
public class LambdaControlsCompat public class LambdaControlsCompat
{ {
private static final List<CompatHandler> HANDLERS = new ArrayList<>();
/** /**
* Initializes compatibility with other mods if needed. * Initializes compatibility with other mods if needed.
* *
@@ -33,8 +39,34 @@ public class LambdaControlsCompat
{ {
if (FabricLoader.getInstance().isModLoaded("okzoomer") && LambdaReflection.doesClassExist(OkZoomerCompat.OKZOOMER_CLASS_PATH)) { if (FabricLoader.getInstance().isModLoaded("okzoomer") && LambdaReflection.doesClassExist(OkZoomerCompat.OKZOOMER_CLASS_PATH)) {
mod.log("Adding okzoomer compatibility..."); mod.log("Adding okzoomer compatibility...");
new OkZoomerCompat().handle(mod); HANDLERS.add(new OkZoomerCompat());
} }
if (isReiPresent()) {
mod.log("Adding REI compatiblity...");
HANDLERS.add(new ReiCompat());
}
HANDLERS.forEach(handler -> handler.handle(mod));
InputManager.loadButtonBindings(mod.config); InputManager.loadButtonBindings(mod.config);
} }
/**
* Returns whether the mouse is required on the specified screen.
*
* @param screen The screen.
* @return True if the mouse is requried on the specified screen, else false.
*/
public static boolean requireMouseOnScreen(Screen screen)
{
return HANDLERS.stream().anyMatch(handler -> handler.requireMouseOnScreen(screen));
}
/**
* Returns whether Roughly Enough Items is present.
*
* @return True if Roughly Enough Items is present, else false.
*/
public static boolean isReiPresent()
{
return FabricLoader.getInstance().isModLoaded("roughlyenoughitems");
}
} }

View File

@@ -0,0 +1,74 @@
/*
* Copyright © 2020 LambdAurora <aurora42lambda@gmail.com>
*
* This file is part of LambdaControls.
*
* Licensed under the MIT license. For more information,
* see the LICENSE file.
*/
package me.lambdaurora.lambdacontrols.client.compat;
import org.objectweb.asm.tree.ClassNode;
import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin;
import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
/**
* This plugin is only present for the conditional mixins.
*
* @author LambdAurora
* @version 1.2.0
* @since 1.2.0
*/
public class LambdaControlsMixinPlugin implements IMixinConfigPlugin
{
private final HashMap<String, Boolean> conditionalMixins = new HashMap<>();
public LambdaControlsMixinPlugin()
{
this.conditionalMixins.put("me.lambdaurora.lambdacontrols.client.compat.mixin.RecipeViewingScreenAccessor", LambdaControlsCompat.isReiPresent());
this.conditionalMixins.put("me.lambdaurora.lambdacontrols.client.compat.mixin.VillagerRecipeViewingScreenAccessor", LambdaControlsCompat.isReiPresent());
}
@Override
public void onLoad(String mixinPackage)
{
}
@Override
public String getRefMapperConfig()
{
return null;
}
@Override
public boolean shouldApplyMixin(String targetClassName, String mixinClassName)
{
return this.conditionalMixins.getOrDefault(mixinClassName, Boolean.TRUE);
}
@Override
public void acceptTargets(Set<String> myTargets, Set<String> otherTargets)
{
}
@Override
public List<String> getMixins()
{
return null;
}
@Override
public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo)
{
}
@Override
public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo)
{
}
}

View File

@@ -9,7 +9,7 @@
package me.lambdaurora.lambdacontrols.client.compat; package me.lambdaurora.lambdacontrols.client.compat;
import io.github.joaoh1.okzoomer.OkZoomer; import io.github.joaoh1.okzoomer.client.OkZoomerClientMod;
import me.lambdaurora.lambdacontrols.client.LambdaControlsClient; import me.lambdaurora.lambdacontrols.client.LambdaControlsClient;
import me.lambdaurora.lambdacontrols.client.controller.ButtonBinding; import me.lambdaurora.lambdacontrols.client.controller.ButtonBinding;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -19,12 +19,12 @@ import org.lwjgl.glfw.GLFW;
* Represents a compatibility handler for OkZoomer. * Represents a compatibility handler for OkZoomer.
* *
* @author LambdAurora * @author LambdAurora
* @version 1.1.0 * @version 1.3.0
* @since 1.1.0 * @since 1.1.0
*/ */
public class OkZoomerCompat implements CompatHandler public class OkZoomerCompat implements CompatHandler
{ {
public static final String OKZOOMER_CLASS_PATH = "io.github.joaoh1.okzoomer.OkZoomer"; public static final String OKZOOMER_CLASS_PATH = "io.github.joaoh1.okzoomer.client.OkZoomerClientMod";
@Override @Override
public void handle(@NotNull LambdaControlsClient mod) public void handle(@NotNull LambdaControlsClient mod)
@@ -34,7 +34,7 @@ public class OkZoomerCompat implements CompatHandler
.onlyInGame() .onlyInGame()
.cooldown(true) .cooldown(true)
.category(ButtonBinding.MISC_CATEGORY) .category(ButtonBinding.MISC_CATEGORY)
.linkKeybind(OkZoomer.zoomKeyBinding) .linkKeybind(OkZoomerClientMod.zoomKeyBinding)
.register(); .register();
} }
} }

View File

@@ -0,0 +1,178 @@
/*
* Copyright © 2020 LambdAurora <aurora42lambda@gmail.com>
*
* This file is part of LambdaControls.
*
* Licensed under the MIT license. For more information,
* see the LICENSE file.
*/
package me.lambdaurora.lambdacontrols.client.compat;
import me.lambdaurora.lambdacontrols.client.ButtonState;
import me.lambdaurora.lambdacontrols.client.LambdaControlsClient;
import me.lambdaurora.lambdacontrols.client.compat.mixin.RecipeViewingScreenAccessor;
import me.lambdaurora.lambdacontrols.client.compat.mixin.VillagerRecipeViewingScreenAccessor;
import me.lambdaurora.lambdacontrols.client.controller.ButtonBinding;
import me.lambdaurora.lambdacontrols.client.controller.InputHandlers;
import me.lambdaurora.lambdacontrols.client.controller.InputManager;
import me.lambdaurora.lambdacontrols.client.controller.PressAction;
import me.shedaniel.rei.api.RecipeCategory;
import me.shedaniel.rei.gui.ContainerScreenOverlay;
import me.shedaniel.rei.gui.RecipeViewingScreen;
import me.shedaniel.rei.gui.VillagerRecipeViewingScreen;
import me.shedaniel.rei.gui.widget.EntryListWidget;
import me.shedaniel.rei.impl.ScreenHelper;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.util.Identifier;
import org.aperlambda.lambdacommon.utils.LambdaReflection;
import org.jetbrains.annotations.NotNull;
import java.util.List;
import java.util.Optional;
import static org.lwjgl.glfw.GLFW.*;
/**
* Represents a compatibility handler for REI.
*
* @author LambdAurora
* @version 1.3.0
* @since 1.2.0
*/
public class ReiCompat implements CompatHandler
{
private static EntryListWidget ENTRY_LIST_WIDGET;
public static ButtonBinding TAB_BACK;
@Override
public void handle(@NotNull LambdaControlsClient mod)
{
InputManager.registerBinding(new ButtonBinding.Builder(new Identifier("rei", "category_back"))
.buttons(GLFW_GAMEPAD_BUTTON_LEFT_BUMPER)
.filter((client, binding) -> isViewingScreen(client.currentScreen))
.action(handleTab(false))
.cooldown(true)
.build());
InputManager.registerBinding(new ButtonBinding.Builder(new Identifier("rei", "category_next"))
.buttons(GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER)
.filter((client, binding) -> isViewingScreen(client.currentScreen))
.action(handleTab(true))
.cooldown(true)
.build());
InputManager.registerBinding(new ButtonBinding.Builder(new Identifier("rei", "page_back"))
.buttons(ButtonBinding.axisAsButton(GLFW_GAMEPAD_AXIS_RIGHT_X, false))
.filter((client, binding) -> InputHandlers.inInventory(client, binding) || isViewingScreen(client.currentScreen))
.action(handlePage(false))
.cooldown(true)
.build());
InputManager.registerBinding(new ButtonBinding.Builder(new Identifier("rei", "page_next"))
.buttons(ButtonBinding.axisAsButton(GLFW_GAMEPAD_AXIS_RIGHT_X, true))
.filter((client, binding) -> InputHandlers.inInventory(client, binding) || isViewingScreen(client.currentScreen))
.action(handlePage(true))
.cooldown(true)
.build());
// For some reasons this is broken.
InputManager.registerBinding(new ButtonBinding.Builder(new Identifier("rei", "show_usage"))
.buttons(GLFW_GAMEPAD_BUTTON_RIGHT_THUMB)
.filter((client, binding) -> InputHandlers.inInventory(client, binding) || isViewingScreen(client.currentScreen))
.action((client, button, action) -> {
if (action != ButtonState.RELEASE)
return false;
Optional<ContainerScreenOverlay> overlay = ScreenHelper.getOptionalOverlay();
if (!overlay.isPresent())
return false;
double mouseX = client.mouse.getX();
double mouseY = client.mouse.getY();
EntryListWidget widget = getEntryListWidget();
if (widget == null)
return false;
return widget.mouseClicked(mouseX, mouseY, GLFW_MOUSE_BUTTON_2);
})
.cooldown(true)
.build());
}
@Override
public boolean requireMouseOnScreen(Screen screen)
{
return isViewingScreen(screen);
}
private static boolean isViewingScreen(Screen screen)
{
return screen instanceof RecipeViewingScreen || screen instanceof VillagerRecipeViewingScreen;
}
private static EntryListWidget getEntryListWidget()
{
if (ENTRY_LIST_WIDGET == null) {
ENTRY_LIST_WIDGET = LambdaReflection.getFirstFieldOfType(ContainerScreenOverlay.class, EntryListWidget.class)
.map(field -> (EntryListWidget) LambdaReflection.getFieldValue(null, field))
.orElse(null);
}
return ENTRY_LIST_WIDGET;
}
private static PressAction handlePage(boolean next)
{
return (client, button, action) -> {
if (action == ButtonState.RELEASE)
return false;
Optional<ContainerScreenOverlay> overlay = ScreenHelper.getOptionalOverlay();
if (!overlay.isPresent())
return false;
EntryListWidget widget = getEntryListWidget();
if (widget == null)
return false;
if (next)
widget.nextPage();
else
widget.previousPage();
widget.updateEntriesPosition();
return true;
};
}
/**
* Returns the handler for category tabs buttons.
*
* @param next True if the action is to switch to the next tab.
* @return The handler.
*/
private static PressAction handleTab(boolean next)
{
return (client, button, action) -> {
if (action != ButtonState.RELEASE)
return false;
if (client.currentScreen instanceof RecipeViewingScreen) {
RecipeViewingScreenAccessor screen = (RecipeViewingScreenAccessor) client.currentScreen;
if (next)
screen.getCategoryNext().onClick();
else
screen.getCategoryBack().onClick();
return true;
} else if (client.currentScreen instanceof VillagerRecipeViewingScreen) {
VillagerRecipeViewingScreenAccessor screen = (VillagerRecipeViewingScreenAccessor) client.currentScreen;
List<RecipeCategory<?>> categories = screen.getCategories();
int currentTab = screen.getSelectedCategoryIndex();
int nextTab = currentTab + (next ? 1 : -1);
if (nextTab < 0)
nextTab = categories.size() - 1;
else if (nextTab >= categories.size())
nextTab = 0;
screen.setSelectedCategoryIndex(nextTab);
screen.lambdacontrols_init();
return true;
}
return false;
};
}
}

View File

@@ -0,0 +1,32 @@
/*
* Copyright © 2020 LambdAurora <aurora42lambda@gmail.com>
*
* This file is part of LambdaControls.
*
* Licensed under the MIT license. For more information,
* see the LICENSE file.
*/
package me.lambdaurora.lambdacontrols.client.compat.mixin;
import me.shedaniel.rei.api.widgets.Button;
import me.shedaniel.rei.gui.RecipeViewingScreen;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
/**
* Represents an accessor to REI's RecipeViewingScreen.
*
* @author LambdAurora
* @version 1.3.0
* @since 1.2.0
*/
@Mixin(RecipeViewingScreen.class)
public interface RecipeViewingScreenAccessor
{
@Accessor("categoryBack")
Button getCategoryBack();
@Accessor("categoryNext")
Button getCategoryNext();
}

View File

@@ -0,0 +1,41 @@
/*
* Copyright © 2020 LambdAurora <aurora42lambda@gmail.com>
*
* This file is part of LambdaControls.
*
* Licensed under the MIT license. For more information,
* see the LICENSE file.
*/
package me.lambdaurora.lambdacontrols.client.compat.mixin;
import me.shedaniel.rei.api.RecipeCategory;
import me.shedaniel.rei.gui.VillagerRecipeViewingScreen;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import org.spongepowered.asm.mixin.gen.Invoker;
import java.util.List;
/**
* Represents an accessor to REI's VillagerRecipeViewingScreen.
*
* @author LambdAurora
* @version 1.2.0
* @since 1.2.0
*/
@Mixin(VillagerRecipeViewingScreen.class)
public interface VillagerRecipeViewingScreenAccessor
{
@Accessor("categories")
List<RecipeCategory<?>> getCategories();
@Accessor("selectedCategoryIndex")
int getSelectedCategoryIndex();
@Accessor("selectedCategoryIndex")
void setSelectedCategoryIndex(int selectedCategoryIndex);
@Invoker("init")
void lambdacontrols_init();
}

View File

@@ -14,6 +14,8 @@ import net.minecraft.client.MinecraftClient;
import net.minecraft.client.options.GameOptions; import net.minecraft.client.options.GameOptions;
import net.minecraft.client.options.KeyBinding; import net.minecraft.client.options.KeyBinding;
import net.minecraft.client.resource.language.I18n; import net.minecraft.client.resource.language.I18n;
import net.minecraft.text.Text;
import net.minecraft.text.TranslatableText;
import org.aperlambda.lambdacommon.Identifier; import org.aperlambda.lambdacommon.Identifier;
import org.aperlambda.lambdacommon.utils.Nameable; import org.aperlambda.lambdacommon.utils.Nameable;
import org.aperlambda.lambdacommon.utils.function.PairPredicate; import org.aperlambda.lambdacommon.utils.function.PairPredicate;
@@ -31,7 +33,7 @@ import static org.lwjgl.glfw.GLFW.*;
* Represents a button binding. * Represents a button binding.
* *
* @author LambdAurora * @author LambdAurora
* @version 1.1.0 * @version 1.3.0
* @since 1.0.0 * @since 1.0.0
*/ */
public class ButtonBinding implements Nameable public class ButtonBinding implements Nameable
@@ -73,9 +75,9 @@ public class ButtonBinding implements Nameable
.actions(PressAction.DEFAULT_ACTION, InputHandlers::handleToggleSneak).onlyInGame().cooldown(true).register(); .actions(PressAction.DEFAULT_ACTION, InputHandlers::handleToggleSneak).onlyInGame().cooldown(true).register();
public static final ButtonBinding SPRINT = new Builder("sprint").buttons(GLFW_GAMEPAD_BUTTON_LEFT_THUMB).register(); public static final ButtonBinding SPRINT = new Builder("sprint").buttons(GLFW_GAMEPAD_BUTTON_LEFT_THUMB).register();
public static final ButtonBinding SWAP_HANDS = new Builder("swap_hands").buttons(GLFW_GAMEPAD_BUTTON_X).cooldown(true).register(); public static final ButtonBinding SWAP_HANDS = new Builder("swap_hands").buttons(GLFW_GAMEPAD_BUTTON_X).cooldown(true).register();
public static final ButtonBinding TAB_LEFT = new Builder("tab_left").buttons(GLFW_GAMEPAD_BUTTON_LEFT_BUMPER) public static final ButtonBinding TAB_LEFT = new Builder("tab_back").buttons(GLFW_GAMEPAD_BUTTON_LEFT_BUMPER)
.action(InputHandlers.handleHotbar(false)).filter(Predicates.or(InputHandlers::inInventory, InputHandlers::inAdvancements)).cooldown(true).register(); .action(InputHandlers.handleHotbar(false)).filter(Predicates.or(InputHandlers::inInventory, InputHandlers::inAdvancements)).cooldown(true).register();
public static final ButtonBinding TAB_RIGHT = new Builder("tab_right").buttons(GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER) public static final ButtonBinding TAB_RIGHT = new Builder("tab_next").buttons(GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER)
.action(InputHandlers.handleHotbar(true)).filter(Predicates.or(InputHandlers::inInventory, InputHandlers::inAdvancements)).cooldown(true).register(); .action(InputHandlers.handleHotbar(true)).filter(Predicates.or(InputHandlers::inInventory, InputHandlers::inAdvancements)).cooldown(true).register();
public static final ButtonBinding TOGGLE_PERSPECTIVE = new Builder("toggle_perspective").buttons(GLFW_GAMEPAD_BUTTON_DPAD_UP, GLFW_GAMEPAD_BUTTON_Y).cooldown(true).register(); public static final ButtonBinding TOGGLE_PERSPECTIVE = new Builder("toggle_perspective").buttons(GLFW_GAMEPAD_BUTTON_DPAD_UP, GLFW_GAMEPAD_BUTTON_Y).cooldown(true).register();
public static final ButtonBinding USE = new Builder("use").buttons(axisAsButton(GLFW_GAMEPAD_AXIS_LEFT_TRIGGER, true)).register(); public static final ButtonBinding USE = new Builder("use").buttons(axisAsButton(GLFW_GAMEPAD_AXIS_LEFT_TRIGGER, true)).register();
@@ -320,64 +322,63 @@ public class ButtonBinding implements Nameable
* @param button The button. * @param button The button.
* @return The localized name of the button. * @return The localized name of the button.
*/ */
public static @NotNull public static @NotNull Text getLocalizedButtonName(int button)
String getLocalizedButtonName(int button)
{ {
switch (button % 500) { switch (button % 500) {
case -1: case -1:
return I18n.translate("key.keyboard.unknown"); return new TranslatableText("key.keyboard.unknown");
case GLFW_GAMEPAD_BUTTON_A: case GLFW_GAMEPAD_BUTTON_A:
return I18n.translate("lambdacontrols.button.a"); return new TranslatableText("lambdacontrols.button.a");
case GLFW_GAMEPAD_BUTTON_B: case GLFW_GAMEPAD_BUTTON_B:
return I18n.translate("lambdacontrols.button.b"); return new TranslatableText("lambdacontrols.button.b");
case GLFW_GAMEPAD_BUTTON_X: case GLFW_GAMEPAD_BUTTON_X:
return I18n.translate("lambdacontrols.button.x"); return new TranslatableText("lambdacontrols.button.x");
case GLFW_GAMEPAD_BUTTON_Y: case GLFW_GAMEPAD_BUTTON_Y:
return I18n.translate("lambdacontrols.button.y"); return new TranslatableText("lambdacontrols.button.y");
case GLFW_GAMEPAD_BUTTON_LEFT_BUMPER: case GLFW_GAMEPAD_BUTTON_LEFT_BUMPER:
return I18n.translate("lambdacontrols.button.left_bumper"); return new TranslatableText("lambdacontrols.button.left_bumper");
case GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER: case GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER:
return I18n.translate("lambdacontrols.button.right_bumper"); return new TranslatableText("lambdacontrols.button.right_bumper");
case GLFW_GAMEPAD_BUTTON_BACK: case GLFW_GAMEPAD_BUTTON_BACK:
return I18n.translate("lambdacontrols.button.back"); return new TranslatableText("lambdacontrols.button.back");
case GLFW_GAMEPAD_BUTTON_START: case GLFW_GAMEPAD_BUTTON_START:
return I18n.translate("lambdacontrols.button.start"); return new TranslatableText("lambdacontrols.button.start");
case GLFW_GAMEPAD_BUTTON_GUIDE: case GLFW_GAMEPAD_BUTTON_GUIDE:
return I18n.translate("lambdacontrols.button.guide"); return new TranslatableText("lambdacontrols.button.guide");
case GLFW_GAMEPAD_BUTTON_LEFT_THUMB: case GLFW_GAMEPAD_BUTTON_LEFT_THUMB:
return I18n.translate("lambdacontrols.button.left_thumb"); return new TranslatableText("lambdacontrols.button.left_thumb");
case GLFW_GAMEPAD_BUTTON_RIGHT_THUMB: case GLFW_GAMEPAD_BUTTON_RIGHT_THUMB:
return I18n.translate("lambdacontrols.button.right_thumb"); return new TranslatableText("lambdacontrols.button.right_thumb");
case GLFW_GAMEPAD_BUTTON_DPAD_UP: case GLFW_GAMEPAD_BUTTON_DPAD_UP:
return I18n.translate("lambdacontrols.button.dpad_up"); return new TranslatableText("lambdacontrols.button.dpad_up");
case GLFW_GAMEPAD_BUTTON_DPAD_RIGHT: case GLFW_GAMEPAD_BUTTON_DPAD_RIGHT:
return I18n.translate("lambdacontrols.button.dpad_right"); return new TranslatableText("lambdacontrols.button.dpad_right");
case GLFW_GAMEPAD_BUTTON_DPAD_DOWN: case GLFW_GAMEPAD_BUTTON_DPAD_DOWN:
return I18n.translate("lambdacontrols.button.dpad_down"); return new TranslatableText("lambdacontrols.button.dpad_down");
case GLFW_GAMEPAD_BUTTON_DPAD_LEFT: case GLFW_GAMEPAD_BUTTON_DPAD_LEFT:
return I18n.translate("lambdacontrols.button.dpad_left"); return new TranslatableText("lambdacontrols.button.dpad_left");
case 100: case 100:
return I18n.translate("lambdacontrols.axis.left_x+"); return new TranslatableText("lambdacontrols.axis.left_x+");
case 101: case 101:
return I18n.translate("lambdacontrols.axis.left_y+"); return new TranslatableText("lambdacontrols.axis.left_y+");
case 102: case 102:
return I18n.translate("lambdacontrols.axis.right_x+"); return new TranslatableText("lambdacontrols.axis.right_x+");
case 103: case 103:
return I18n.translate("lambdacontrols.axis.right_y+"); return new TranslatableText("lambdacontrols.axis.right_y+");
case 104: case 104:
return I18n.translate("lambdacontrols.axis.left_trigger"); return new TranslatableText("lambdacontrols.axis.left_trigger");
case 105: case 105:
return I18n.translate("lambdacontrols.axis.right_trigger"); return new TranslatableText("lambdacontrols.axis.right_trigger");
case 200: case 200:
return I18n.translate("lambdacontrols.axis.left_x-"); return new TranslatableText("lambdacontrols.axis.left_x-");
case 201: case 201:
return I18n.translate("lambdacontrols.axis.left_y-"); return new TranslatableText("lambdacontrols.axis.left_y-");
case 202: case 202:
return I18n.translate("lambdacontrols.axis.right_x-"); return new TranslatableText("lambdacontrols.axis.right_x-");
case 203: case 203:
return I18n.translate("lambdacontrols.axis.right_y-"); return new TranslatableText("lambdacontrols.axis.right_y-");
default: default:
return I18n.translate("lambdacontrols.button.unknown", button); return new TranslatableText("lambdacontrols.button.unknown", button);
} }
} }

View File

@@ -12,16 +12,19 @@ package me.lambdaurora.lambdacontrols.client.controller;
import me.lambdaurora.lambdacontrols.client.ButtonState; import me.lambdaurora.lambdacontrols.client.ButtonState;
import me.lambdaurora.lambdacontrols.client.mixin.AdvancementsScreenAccessor; import me.lambdaurora.lambdacontrols.client.mixin.AdvancementsScreenAccessor;
import me.lambdaurora.lambdacontrols.client.mixin.CreativeInventoryScreenAccessor; import me.lambdaurora.lambdacontrols.client.mixin.CreativeInventoryScreenAccessor;
import me.lambdaurora.lambdacontrols.client.util.ContainerScreenAccessor; import me.lambdaurora.lambdacontrols.client.mixin.RecipeBookWidgetAccessor;
import me.lambdaurora.lambdacontrols.client.util.HandledScreenAccessor;
import me.lambdaurora.lambdacontrols.client.util.KeyBindingAccessor; import me.lambdaurora.lambdacontrols.client.util.KeyBindingAccessor;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.advancement.AdvancementTab; import net.minecraft.client.gui.screen.advancement.AdvancementTab;
import net.minecraft.client.gui.screen.advancement.AdvancementsScreen; import net.minecraft.client.gui.screen.advancement.AdvancementsScreen;
import net.minecraft.client.gui.screen.ingame.ContainerScreen;
import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen; import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen;
import net.minecraft.client.gui.screen.ingame.HandledScreen;
import net.minecraft.client.gui.screen.ingame.InventoryScreen;
import net.minecraft.client.gui.screen.recipebook.RecipeGroupButtonWidget;
import net.minecraft.client.util.ScreenshotUtils; import net.minecraft.client.util.ScreenshotUtils;
import net.minecraft.container.Slot;
import net.minecraft.item.ItemGroup; import net.minecraft.item.ItemGroup;
import net.minecraft.screen.slot.Slot;
import org.aperlambda.lambdacommon.utils.Pair; import org.aperlambda.lambdacommon.utils.Pair;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -35,7 +38,7 @@ import java.util.stream.Collectors;
* Represents some input handlers. * Represents some input handlers.
* *
* @author LambdAurora * @author LambdAurora
* @version 1.1.0 * @version 1.3.0
* @since 1.1.0 * @since 1.1.0
*/ */
public class InputHandlers public class InputHandlers
@@ -44,7 +47,7 @@ public class InputHandlers
{ {
} }
public static PressAction handleHotbar(boolean right) public static PressAction handleHotbar(boolean next)
{ {
return (client, button, action) -> { return (client, button, action) -> {
if (action == ButtonState.RELEASE) if (action == ButtonState.RELEASE)
@@ -52,33 +55,46 @@ public class InputHandlers
// When ingame // When ingame
if (client.currentScreen == null && client.player != null) { if (client.currentScreen == null && client.player != null) {
if (right) if (next)
client.player.inventory.selectedSlot = client.player.inventory.selectedSlot == 8 ? 0 : client.player.inventory.selectedSlot + 1; client.player.inventory.selectedSlot = client.player.inventory.selectedSlot == 8 ? 0 : client.player.inventory.selectedSlot + 1;
else else
client.player.inventory.selectedSlot = client.player.inventory.selectedSlot == 0 ? 8 : client.player.inventory.selectedSlot - 1; client.player.inventory.selectedSlot = client.player.inventory.selectedSlot == 0 ? 8 : client.player.inventory.selectedSlot - 1;
return true; return true;
} else if (client.currentScreen instanceof CreativeInventoryScreen) { } else if (client.currentScreen instanceof CreativeInventoryScreen) {
CreativeInventoryScreenAccessor inventory = (CreativeInventoryScreenAccessor) client.currentScreen; CreativeInventoryScreenAccessor inventory = (CreativeInventoryScreenAccessor) client.currentScreen;
int currentSelectedTab = inventory.lambdacontrols_getSelectedTab(); int currentTab = inventory.getSelectedTab();
int nextTab = currentSelectedTab + (right ? 1 : -1); int nextTab = currentTab + (next ? 1 : -1);
if (nextTab < 0) if (nextTab < 0)
nextTab = ItemGroup.GROUPS.length - 1; nextTab = ItemGroup.GROUPS.length - 1;
else if (nextTab >= ItemGroup.GROUPS.length) else if (nextTab >= ItemGroup.GROUPS.length)
nextTab = 0; nextTab = 0;
inventory.lambdacontrols_setSelectedTab(ItemGroup.GROUPS[nextTab]); inventory.lambdacontrols_setSelectedTab(ItemGroup.GROUPS[nextTab]);
return true; return true;
} else if (client.currentScreen instanceof InventoryScreen) {
RecipeBookWidgetAccessor recipeBook = (RecipeBookWidgetAccessor) ((InventoryScreen) client.currentScreen).getRecipeBookWidget();
List<RecipeGroupButtonWidget> tabs = recipeBook.getTabButtons();
RecipeGroupButtonWidget currentTab = recipeBook.getCurrentTab();
int nextTab = tabs.indexOf(currentTab) + (next ? 1 : -1);
if (nextTab < 0)
nextTab = tabs.size() - 1;
else if (nextTab >= tabs.size())
nextTab = 0;
currentTab.setToggled(false);
recipeBook.setCurrentTab(currentTab = tabs.get(nextTab));
currentTab.setToggled(true);
recipeBook.lambdacontrols_refreshResults(true);
} else if (client.currentScreen instanceof AdvancementsScreen) { } else if (client.currentScreen instanceof AdvancementsScreen) {
AdvancementsScreenAccessor screen = (AdvancementsScreenAccessor) client.currentScreen; AdvancementsScreenAccessor screen = (AdvancementsScreenAccessor) client.currentScreen;
List<AdvancementTab> tabs = screen.lambdacontrols_getTabs().values().stream().distinct().collect(Collectors.toList()); List<AdvancementTab> tabs = screen.getTabs().values().stream().distinct().collect(Collectors.toList());
AdvancementTab tab = screen.lambdacontrols_getSelectedTab(); AdvancementTab tab = screen.getSelectedTab();
for (int i = 0; i < tabs.size(); i++) { for (int i = 0; i < tabs.size(); i++) {
if (tabs.get(i).equals(tab)) { if (tabs.get(i).equals(tab)) {
int nextTab = i + (right ? 1 : -1); int nextTab = i + (next ? 1 : -1);
if (nextTab < 0) if (nextTab < 0)
nextTab = tabs.size() - 1; nextTab = tabs.size() - 1;
else if (nextTab >= tabs.size()) else if (nextTab >= tabs.size())
nextTab = 0; nextTab = 0;
screen.lambdacontrols_getAdvancementManager().selectTab(tabs.get(nextTab).getRoot(), true); screen.getAdvancementManager().selectTab(tabs.get(nextTab).getRoot(), true);
break; break;
} }
} }
@@ -93,8 +109,8 @@ public class InputHandlers
// If in game, then pause the game. // If in game, then pause the game.
if (client.currentScreen == null) if (client.currentScreen == null)
client.openPauseMenu(false); client.openPauseMenu(false);
else if (client.currentScreen instanceof ContainerScreen && client.player != null) // If the current screen is a container then close it. else if (client.currentScreen instanceof HandledScreen && client.player != null) // If the current screen is a container then close it.
client.player.closeContainer(); client.player.closeHandledScreen();
else // Else just close the current screen. else // Else just close the current screen.
client.currentScreen.onClose(); client.currentScreen.onClose();
} }
@@ -129,13 +145,13 @@ public class InputHandlers
public static PressAction handleInventorySlotPad(int direction) public static PressAction handleInventorySlotPad(int direction)
{ {
return (client, binding, action) -> { return (client, binding, action) -> {
if (!(client.currentScreen instanceof ContainerScreen && action != ButtonState.RELEASE)) if (!(client.currentScreen instanceof HandledScreen && action != ButtonState.RELEASE))
return false; return false;
ContainerScreen inventory = (ContainerScreen) client.currentScreen; HandledScreen inventory = (HandledScreen) client.currentScreen;
ContainerScreenAccessor accessor = (ContainerScreenAccessor) inventory; HandledScreenAccessor accessor = (HandledScreenAccessor) inventory;
int guiLeft = accessor.lambdacontrols_getX(); int guiLeft = accessor.getX();
int guiTop = accessor.lambdacontrols_getY(); int guiTop = accessor.getY();
double mouseX = client.mouse.getX() * (double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth(); double mouseX = client.mouse.getX() * (double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth();
double mouseY = client.mouse.getY() * (double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight(); double mouseY = client.mouse.getY() * (double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight();
@@ -143,17 +159,17 @@ public class InputHandlers
Slot mouseSlot = accessor.lambdacontrols_getSlotAt(mouseX, mouseY); Slot mouseSlot = accessor.lambdacontrols_getSlotAt(mouseX, mouseY);
// Finds the closest slot in the GUI within 14 pixels. // Finds the closest slot in the GUI within 14 pixels.
Optional<Slot> closestSlot = inventory.getContainer().slots.parallelStream() Optional<Slot> closestSlot = inventory.getScreenHandler().slots.parallelStream()
.filter(Predicate.isEqual(mouseSlot).negate()) .filter(Predicate.isEqual(mouseSlot).negate())
.map(slot -> { .map(slot -> {
int posX = guiLeft + slot.xPosition + 8; int posX = guiLeft + slot.x + 8;
int posY = guiTop + slot.yPosition + 8; int posY = guiTop + slot.y + 8;
int otherPosX = (int) mouseX; int otherPosX = (int) mouseX;
int otherPosY = (int) mouseY; int otherPosY = (int) mouseY;
if (mouseSlot != null) { if (mouseSlot != null) {
otherPosX = guiLeft + mouseSlot.xPosition + 8; otherPosX = guiLeft + mouseSlot.x + 8;
otherPosY = guiTop + mouseSlot.yPosition + 8; otherPosY = guiTop + mouseSlot.y + 8;
} }
// Distance between the slot and the cursor. // Distance between the slot and the cursor.
@@ -161,13 +177,13 @@ public class InputHandlers
return Pair.of(slot, distance); return Pair.of(slot, distance);
}).filter(entry -> { }).filter(entry -> {
Slot slot = entry.key; Slot slot = entry.key;
int posX = guiLeft + slot.xPosition + 8; int posX = guiLeft + slot.x + 8;
int posY = guiTop + slot.yPosition + 8; int posY = guiTop + slot.y + 8;
int otherPosX = (int) mouseX; int otherPosX = (int) mouseX;
int otherPosY = (int) mouseY; int otherPosY = (int) mouseY;
if (mouseSlot != null) { if (mouseSlot != null) {
otherPosX = guiLeft + mouseSlot.xPosition + 8; otherPosX = guiLeft + mouseSlot.x + 8;
otherPosY = guiTop + mouseSlot.yPosition + 8; otherPosY = guiTop + mouseSlot.y + 8;
} }
if (direction == 0) if (direction == 0)
return posY < otherPosY; return posY < otherPosY;
@@ -185,8 +201,8 @@ public class InputHandlers
if (closestSlot.isPresent()) { if (closestSlot.isPresent()) {
Slot slot = closestSlot.get(); Slot slot = closestSlot.get();
int x = guiLeft + slot.xPosition + 8; int x = guiLeft + slot.x + 8;
int y = guiTop + slot.yPosition + 8; int y = guiTop + slot.y + 8;
InputManager.queueMousePosition(x * (double) client.getWindow().getWidth() / (double) client.getWindow().getScaledWidth(), InputManager.queueMousePosition(x * (double) client.getWindow().getWidth() / (double) client.getWindow().getScaledWidth(),
y * (double) client.getWindow().getHeight() / (double) client.getWindow().getScaledHeight()); y * (double) client.getWindow().getHeight() / (double) client.getWindow().getScaledHeight());
return true; return true;
@@ -228,7 +244,7 @@ public class InputHandlers
*/ */
public static boolean inInventory(@NotNull MinecraftClient client, @NotNull ButtonBinding binding) public static boolean inInventory(@NotNull MinecraftClient client, @NotNull ButtonBinding binding)
{ {
return client.currentScreen instanceof ContainerScreen; return client.currentScreen instanceof HandledScreen;
} }
/** /**

View File

@@ -15,6 +15,8 @@ import me.lambdaurora.lambdacontrols.client.LambdaControlsClient;
import me.lambdaurora.lambdacontrols.client.LambdaControlsConfig; import me.lambdaurora.lambdacontrols.client.LambdaControlsConfig;
import me.lambdaurora.lambdacontrols.client.util.MouseAccessor; import me.lambdaurora.lambdacontrols.client.util.MouseAccessor;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.client.options.KeyBinding;
import net.minecraft.client.util.InputUtil;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.MathHelper;
import org.aperlambda.lambdacommon.Identifier; import org.aperlambda.lambdacommon.Identifier;
import org.aperlambda.lambdacommon.utils.function.PairPredicate; import org.aperlambda.lambdacommon.utils.function.PairPredicate;
@@ -30,7 +32,7 @@ import java.util.stream.Stream;
* Represents an input manager for controllers. * Represents an input manager for controllers.
* *
* @author LambdAurora * @author LambdAurora
* @version 1.1.0 * @version 1.3.0
* @since 1.1.0 * @since 1.1.0
*/ */
public class InputManager public class InputManager
@@ -72,7 +74,8 @@ public class InputManager
if (this.prevTargetMouseX != this.targetMouseX || this.prevTargetMouseY != this.targetMouseY) { if (this.prevTargetMouseX != this.targetMouseX || this.prevTargetMouseY != this.targetMouseY) {
double mouseX = this.prevTargetMouseX + (this.targetMouseX - this.prevTargetMouseX) * client.getTickDelta() + 0.5; double mouseX = this.prevTargetMouseX + (this.targetMouseX - this.prevTargetMouseX) * client.getTickDelta() + 0.5;
double mouseY = this.prevTargetMouseY + (this.targetMouseY - this.prevTargetMouseY) * client.getTickDelta() + 0.5; double mouseY = this.prevTargetMouseY + (this.targetMouseY - this.prevTargetMouseY) * client.getTickDelta() + 0.5;
GLFW.glfwSetCursorPos(client.getWindow().getHandle(), mouseX, mouseY); if (!LambdaControlsClient.get().config.hasVirtualMouse())
GLFW.glfwSetCursorPos(client.getWindow().getHandle(), mouseX, mouseY);
((MouseAccessor) client.mouse).lambdacontrols_onCursorPos(client.getWindow().getHandle(), mouseX, mouseY); ((MouseAccessor) client.mouse).lambdacontrols_onCursorPos(client.getWindow().getHandle(), mouseX, mouseY);
} }
} }
@@ -357,4 +360,34 @@ public class InputManager
{ {
return CATEGORIES.stream(); return CATEGORIES.stream();
} }
/**
* Returns a new key binding instance.
* @param id The identifier of the key binding.
* @param type The type.
* @param code The code.
* @param category The category of the key binding.
* @return The key binding.
*
* @see #makeKeyBinding(Identifier, InputUtil.Type, int, String)
*/
public static @NotNull KeyBinding makeKeyBinding(@NotNull net.minecraft.util.Identifier id, InputUtil.Type type, int code, @NotNull String category)
{
return makeKeyBinding(new Identifier(id.getNamespace(), id.getPath()), type, code, category);
}
/**
* Returns a new key binding instance.
* @param id The identifier of the key binding.
* @param type The type.
* @param code The code.
* @param category The category of the key binding.
* @return The key binding.
*
* @see #makeKeyBinding(net.minecraft.util.Identifier, InputUtil.Type, int, String)
*/
public static @NotNull KeyBinding makeKeyBinding(@NotNull Identifier id, InputUtil.Type type, int code, @NotNull String category)
{
return new KeyBinding(String.format("key.%s.%s", id.getNamespace(), id.getName()), type, code, category);
}
} }

View File

@@ -9,11 +9,13 @@
package me.lambdaurora.lambdacontrols.client.gui; package me.lambdaurora.lambdacontrols.client.gui;
import me.lambdaurora.lambdacontrols.client.LambdaControlsClient; import me.lambdaurora.lambdacontrols.LambdaControls;
import me.lambdaurora.lambdacontrols.client.controller.ButtonBinding; import me.lambdaurora.lambdacontrols.client.controller.ButtonBinding;
import me.lambdaurora.spruceui.AbstractIconButtonWidget; import me.lambdaurora.spruceui.AbstractIconButtonWidget;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.client.resource.language.I18n; import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.text.LiteralText;
import net.minecraft.text.Text;
import org.aperlambda.lambdacommon.utils.Pair; import org.aperlambda.lambdacommon.utils.Pair;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -34,25 +36,25 @@ public class ControllerButtonWidget extends AbstractIconButtonWidget
public void update() public void update()
{ {
int length = binding.getButton().length; int length = binding.getButton().length;
this.setMessage(this.binding.isNotBound() ? I18n.translate("lambdacontrols.not_bound") : this.setMessage(this.binding.isNotBound() ? LambdaControls.NOT_BOUND_TEXT :
(length > 0 ? ButtonBinding.getLocalizedButtonName(binding.getButton()[0]) : "<>")); (length > 0 ? ButtonBinding.getLocalizedButtonName(binding.getButton()[0]) : new LiteralText("<>")));
} }
@Override @Override
public String getMessage() public Text getMessage()
{ {
if (this.binding.getButton().length > 1) if (this.binding.getButton().length > 1)
return ""; return LiteralText.EMPTY;
return super.getMessage(); return super.getMessage();
} }
@Override @Override
protected int renderIcon(int mouseX, int mouseY, float delta, int x, int y) protected int renderIcon(MatrixStack matrices, int mouseX, int mouseY, float delta, int x, int y)
{ {
if (this.binding.getButton().length > 1) { if (this.binding.getButton().length > 1) {
x += (this.width / 2 - this.iconWidth / 2) - 4; x += (this.width / 2 - this.iconWidth / 2) - 4;
} }
Pair<Integer, Integer> size = LambdaControlsClient.drawButton(x, y, this.binding, MinecraftClient.getInstance()); Pair<Integer, Integer> size = LambdaControlsRenderer.drawButton(matrices, x, y, this.binding, MinecraftClient.getInstance());
this.iconWidth = size.key; this.iconWidth = size.key;
return size.value; return size.value;
} }

View File

@@ -16,7 +16,7 @@ import me.lambdaurora.spruceui.SpruceButtonWidget;
import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.screen.options.ControlsOptionsScreen; import net.minecraft.client.gui.screen.options.ControlsOptionsScreen;
import net.minecraft.client.gui.widget.ButtonWidget; import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.client.resource.language.I18n; import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.text.TranslatableText; import net.minecraft.text.TranslatableText;
import org.aperlambda.lambdacommon.utils.function.Predicates; import org.aperlambda.lambdacommon.utils.function.Predicates;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -56,26 +56,30 @@ public class ControllerControlsScreen extends Screen
@Override @Override
protected void init() protected void init()
{ {
this.addButton(new SpruceButtonWidget(this.width / 2 - 155, 18, this.hideSettings ? 310 : 150, 20, I18n.translate("lambdacontrols.menu.keyboard_controls"), this.addButton(new SpruceButtonWidget(this.width / 2 - 155, 18, this.hideSettings ? 310 : 150, 20,
btn -> this.minecraft.openScreen(new ControlsOptionsScreen(this, this.minecraft.options)))); new TranslatableText("lambdacontrols.menu.keyboard_controls"),
btn -> this.client.openScreen(new ControlsOptionsScreen(this, this.client.options))));
if (!this.hideSettings) if (!this.hideSettings)
this.addButton(new SpruceButtonWidget(this.width / 2 - 155 + 160, 18, 150, 20, I18n.translate("menu.options"), this.addButton(new SpruceButtonWidget(this.width / 2 - 155 + 160, 18, 150, 20,
btn -> this.minecraft.openScreen(new LambdaControlsSettingsScreen(this, this.minecraft.options, true)))); new TranslatableText("menu.options"),
this.bindingsListWidget = new ControlsListWidget(this, this.minecraft); btn -> this.client.openScreen(new LambdaControlsSettingsScreen(this, true))));
this.bindingsListWidget = new ControlsListWidget(this, this.client);
this.children.add(this.bindingsListWidget); this.children.add(this.bindingsListWidget);
this.resetButton = this.addButton(new ButtonWidget(this.width / 2 - 155, this.height - 29, 150, 20, I18n.translate("controls.resetAll"), this.resetButton = this.addButton(new ButtonWidget(this.width / 2 - 155, this.height - 29, 150, 20,
new TranslatableText("controls.resetAll"),
btn -> InputManager.streamBindings().forEach(binding -> this.mod.config.setButtonBinding(binding, binding.getDefaultButton())))); btn -> InputManager.streamBindings().forEach(binding -> this.mod.config.setButtonBinding(binding, binding.getDefaultButton()))));
this.addButton(new ButtonWidget(this.width / 2 - 155 + 160, this.height - 29, 150, 20, I18n.translate("gui.done"), this.addButton(new ButtonWidget(this.width / 2 - 155 + 160, this.height - 29, 150, 20,
btn -> this.minecraft.openScreen(this.parent))); new TranslatableText("gui.done"),
btn -> this.client.openScreen(this.parent)));
} }
@Override @Override
public void render(int mouseX, int mouseY, float delta) public void render(MatrixStack matrices, int mouseX, int mouseY, float delta)
{ {
this.renderBackground(); this.renderBackground(matrices);
this.bindingsListWidget.render(mouseX, mouseY, delta); this.bindingsListWidget.render(matrices, mouseX, mouseY, delta);
this.drawCenteredString(this.font, this.title.asFormattedString(), this.width / 2, 8, 16777215); this.drawCenteredText(matrices, this.textRenderer, this.title, this.width / 2, 8, 16777215);
this.resetButton.active = InputManager.streamBindings().anyMatch(Predicates.not(ButtonBinding::isDefault)); this.resetButton.active = InputManager.streamBindings().anyMatch(Predicates.not(ButtonBinding::isDefault));
super.render(mouseX, mouseY, delta); super.render(matrices, mouseX, mouseY, delta);
} }
} }

View File

@@ -20,6 +20,10 @@ import net.minecraft.client.gui.Element;
import net.minecraft.client.gui.widget.ButtonWidget; import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.client.gui.widget.ElementListWidget; import net.minecraft.client.gui.widget.ElementListWidget;
import net.minecraft.client.resource.language.I18n; import net.minecraft.client.resource.language.I18n;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.text.LiteralText;
import net.minecraft.text.MutableText;
import net.minecraft.text.TranslatableText;
import net.minecraft.util.Formatting; import net.minecraft.util.Formatting;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -48,7 +52,7 @@ public class ControlsListWidget extends ElementListWidget<ControlsListWidget.Ent
this.addEntry(new CategoryEntry(category)); this.addEntry(new CategoryEntry(category));
category.getBindings().forEach(binding -> { category.getBindings().forEach(binding -> {
int i = client.textRenderer.getStringWidth(I18n.translate(binding.getTranslationKey())); int i = client.textRenderer.getWidth(I18n.translate(binding.getTranslationKey()));
if (i > this.field_2733) { if (i > this.field_2733) {
this.field_2733 = i; this.field_2733 = i;
} }
@@ -59,9 +63,9 @@ public class ControlsListWidget extends ElementListWidget<ControlsListWidget.Ent
} }
@Override @Override
protected int getScrollbarPosition() protected int getScrollbarPositionX()
{ {
return super.getScrollbarPosition() + 15; return super.getScrollbarPositionX() + 15;
} }
@Override @Override
@@ -88,28 +92,28 @@ public class ControlsListWidget extends ElementListWidget<ControlsListWidget.Ent
gui.waiting = true; gui.waiting = true;
}) })
{ {
protected String getNarrationMessage() protected MutableText getNarrationMessage()
{ {
return binding.isNotBound() ? I18n.translate("narrator.controls.unbound", bindingName) : I18n.translate("narrator.controls.bound", bindingName, super.getNarrationMessage()); return binding.isNotBound() ? new TranslatableText("narrator.controls.unbound", bindingName) : new TranslatableText("narrator.controls.bound", bindingName, super.getNarrationMessage());
} }
}; };
this.resetButton = new ButtonWidget(0, 0, 50, 20, I18n.translate("controls.reset"), this.resetButton = new ButtonWidget(0, 0, 50, 20, new TranslatableText("controls.reset"),
btn -> gui.mod.config.setButtonBinding(binding, binding.getDefaultButton())) btn -> gui.mod.config.setButtonBinding(binding, binding.getDefaultButton()))
{ {
protected String getNarrationMessage() protected MutableText getNarrationMessage()
{ {
return I18n.translate("narrator.controls.reset", bindingName); return new TranslatableText("narrator.controls.reset", bindingName);
} }
}; };
this.unboundButton = new ButtonWidget(0, 0, 50, 20, I18n.translate("lambdacontrols.menu.unbound"), this.unboundButton = new ButtonWidget(0, 0, 50, 20, new TranslatableText("lambdacontrols.menu.unbound"),
btn -> { btn -> {
gui.mod.config.setButtonBinding(binding, UNBOUND); gui.mod.config.setButtonBinding(binding, UNBOUND);
gui.focusedBinding = null; gui.focusedBinding = null;
}) })
{ {
protected String getNarrationMessage() protected MutableText getNarrationMessage()
{ {
return I18n.translate("lambdacontrols.narrator.unbound", bindingName); return new TranslatableText("lambdacontrols.narrator.unbound", bindingName);
} }
}; };
} }
@@ -121,34 +125,38 @@ public class ControlsListWidget extends ElementListWidget<ControlsListWidget.Ent
} }
@Override @Override
public void render(int index, int y, int x, int width, int height, int mouseX, int mouseY, boolean hovering, float delta) public void render(MatrixStack matrices, int index, int y, int x, int width, int height, int mouseX, int mouseY, boolean hovering, float delta)
{ {
boolean focused = gui.focusedBinding == this.binding; boolean focused = gui.focusedBinding == this.binding;
TextRenderer textRenderer = ControlsListWidget.this.minecraft.textRenderer; TextRenderer textRenderer = ControlsListWidget.this.client.textRenderer;
String bindingName = this.bindingName; String bindingName = this.bindingName;
float var10002 = (float) (x + 70 - ControlsListWidget.this.field_2733); float var10002 = (float) (x + 70 - ControlsListWidget.this.field_2733);
int var10003 = y + height / 2; int var10003 = y + height / 2;
textRenderer.draw(bindingName, var10002, (float) (var10003 - 9 / 2), 16777215); textRenderer.draw(matrices, bindingName, var10002, (float) (var10003 - 9 / 2), 16777215);
this.resetButton.x = this.unboundButton.x = x + 190; this.resetButton.x = this.unboundButton.x = x + 190;
this.resetButton.y = this.unboundButton.y = y; this.resetButton.y = this.unboundButton.y = y;
this.resetButton.active = !this.binding.isDefault(); this.resetButton.active = !this.binding.isDefault();
if (focused) if (focused)
this.unboundButton.render(mouseX, mouseY, delta); this.unboundButton.render(matrices, mouseX, mouseY, delta);
else else
this.resetButton.render(mouseX, mouseY, delta); this.resetButton.render(matrices, mouseX, mouseY, delta);
this.editButton.x = x + 75; this.editButton.x = x + 75;
this.editButton.y = y; this.editButton.y = y;
this.editButton.update(); this.editButton.update();
if (focused) { if (focused) {
this.editButton.setMessage(Formatting.WHITE + "> " + Formatting.YELLOW + this.editButton.getMessage() + Formatting.WHITE + " <"); MutableText text = new LiteralText("> ").formatted(Formatting.WHITE);
text.append(this.editButton.getMessage().copy().formatted(Formatting.YELLOW));
this.editButton.setMessage(text.append(new LiteralText(" <").formatted(Formatting.WHITE)));
} else if (!this.binding.isNotBound() && InputManager.hasDuplicatedBindings(this.binding)) { } else if (!this.binding.isNotBound() && InputManager.hasDuplicatedBindings(this.binding)) {
this.editButton.setMessage(Formatting.RED + this.editButton.getMessage()); MutableText text = this.editButton.getMessage().copy();
this.editButton.setMessage(text.formatted(Formatting.RED));
} else if (this.binding.isNotBound()) { } else if (this.binding.isNotBound()) {
this.editButton.setMessage(Formatting.GOLD + this.editButton.getMessage()); MutableText text = this.editButton.getMessage().copy();
this.editButton.setMessage(text.formatted(Formatting.GOLD));
} }
this.editButton.render(mouseX, mouseY, delta); this.editButton.render(matrices, mouseX, mouseY, delta);
} }
public boolean mouseClicked(double mouseX, double mouseY, int button) public boolean mouseClicked(double mouseX, double mouseY, int button)
@@ -175,13 +183,13 @@ public class ControlsListWidget extends ElementListWidget<ControlsListWidget.Ent
public CategoryEntry(@NotNull ButtonCategory category) public CategoryEntry(@NotNull ButtonCategory category)
{ {
this.name = category.getTranslatedName(); this.name = category.getTranslatedName();
this.nameWidth = ControlsListWidget.this.minecraft.textRenderer.getStringWidth(this.name); this.nameWidth = ControlsListWidget.this.client.textRenderer.getWidth(this.name);
} }
@Override @Override
public void render(int index, int y, int x, int width, int height, int mouseX, int mouseY, boolean hovering, float delta) public void render(MatrixStack matrices, int index, int y, int x, int width, int height, int mouseX, int mouseY, boolean hovering, float delta)
{ {
ControlsListWidget.this.minecraft.textRenderer.draw(this.name, (float) (ControlsListWidget.this.minecraft.currentScreen.width / 2 - this.nameWidth / 2), ControlsListWidget.this.client.textRenderer.draw(matrices, this.name, (float) (ControlsListWidget.this.client.currentScreen.width / 2 - this.nameWidth / 2),
(float) ((y + height) - 9 - 1), 16777215); (float) ((y + height) - 9 - 1), 16777215);
} }

View File

@@ -13,26 +13,44 @@ import me.lambdaurora.lambdacontrols.ControlsMode;
import me.lambdaurora.lambdacontrols.LambdaControlsConstants; import me.lambdaurora.lambdacontrols.LambdaControlsConstants;
import me.lambdaurora.lambdacontrols.client.HudSide; import me.lambdaurora.lambdacontrols.client.HudSide;
import me.lambdaurora.lambdacontrols.client.LambdaControlsClient; import me.lambdaurora.lambdacontrols.client.LambdaControlsClient;
import me.lambdaurora.lambdacontrols.client.LambdaInput;
import me.lambdaurora.lambdacontrols.client.controller.ButtonBinding; import me.lambdaurora.lambdacontrols.client.controller.ButtonBinding;
import me.lambdaurora.spruceui.hud.Hud; import me.lambdaurora.spruceui.hud.Hud;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.client.resource.language.I18n;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.item.BlockItem;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.hit.HitResult; import net.minecraft.util.hit.HitResult;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/** /**
* Represents the LambdaControls HUD. * Represents the LambdaControls HUD.
* *
* @author LambdAurora * @author LambdAurora
* @version 1.1.0 * @version 1.3.0
* @since 1.0.0 * @since 1.0.0
*/ */
public class LambdaControlsHud extends Hud public class LambdaControlsHud extends Hud
{ {
private final LambdaControlsClient mod; private final LambdaControlsClient mod;
private MinecraftClient client; private MinecraftClient client;
private int widthBottom = 0; private int attackWidth = 0;
private int widthTop = 0; private int attackButtonWidth = 0;
private int dropItemWidth = 0;
private int dropItemButtonWidth = 0;
private int inventoryWidth = 0;
private int inventoryButtonWidth = 0;
private int swapHandsWidth = 0;
private int swapHandsButtonWidth = 0;
private int useWidth = 0;
private int useButtonWidth = 0;
private BlockHitResult placeHitResult;
private String attackAction = "";
private String placeAction = "";
public LambdaControlsHud(@NotNull LambdaControlsClient mod) public LambdaControlsHud(@NotNull LambdaControlsClient mod)
{ {
@@ -45,37 +63,194 @@ public class LambdaControlsHud extends Hud
{ {
super.init(client, screenWidth, screenHeight); super.init(client, screenWidth, screenHeight);
this.client = client; this.client = client;
this.inventoryWidth = this.width(ButtonBinding.INVENTORY);
this.inventoryButtonWidth = LambdaControlsRenderer.getBindingIconWidth(ButtonBinding.INVENTORY);
this.swapHandsWidth = this.width(ButtonBinding.SWAP_HANDS);
this.swapHandsButtonWidth = LambdaControlsRenderer.getBindingIconWidth(ButtonBinding.SWAP_HANDS);
this.dropItemWidth = this.width(ButtonBinding.DROP_ITEM);
this.dropItemButtonWidth = LambdaControlsRenderer.getBindingIconWidth(ButtonBinding.DROP_ITEM);
this.attackButtonWidth = LambdaControlsRenderer.getBindingIconWidth(ButtonBinding.ATTACK);
this.useButtonWidth = LambdaControlsRenderer.getBindingIconWidth(ButtonBinding.USE);
} }
/** /**
* Renders the LambdaControls' HUD. * Renders the LambdaControls' HUD.
*/ */
public void render(float tickDelta) @Override
public void render(MatrixStack matrices, float tickDelta)
{ {
if (this.mod.config.getControlsMode() == ControlsMode.CONTROLLER && this.client.currentScreen == null) { if (this.mod.config.getControlsMode() == ControlsMode.CONTROLLER && this.client.currentScreen == null) {
int x = this.mod.config.getHudSide() == HudSide.LEFT ? 10 : client.getWindow().getScaledWidth() - 10 - this.widthBottom, y = bottom(10); int y = bottom(2);
x += (this.widthBottom = this.drawButtonTip(x, y, ButtonBinding.INVENTORY, true) + 10); this.renderFirstIcons(matrices, this.mod.config.getHudSide() == HudSide.LEFT ? 2 : client.getWindow().getScaledWidth() - 2, y);
this.widthBottom += this.drawButtonTip(x, y, ButtonBinding.SWAP_HANDS, true); this.renderSecondIcons(matrices, this.mod.config.getHudSide() == HudSide.RIGHT ? 2 : client.getWindow().getScaledWidth() - 2, y);
x = this.mod.config.getHudSide() == HudSide.LEFT ? 10 : client.getWindow().getScaledWidth() - 10 - this.widthTop; this.renderFirstSection(matrices, this.mod.config.getHudSide() == HudSide.LEFT ? 2 : client.getWindow().getScaledWidth() - 2, y);
x += (this.widthTop = this.drawButtonTip(x, (y -= 20), ButtonBinding.DROP_ITEM, !this.client.player.getMainHandStack().isEmpty()) + 10); this.renderSecondSection(matrices, this.mod.config.getHudSide() == HudSide.RIGHT ? 2 : client.getWindow().getScaledWidth() - 2, y);
this.widthTop += this.drawButtonTip(x, y, ButtonBinding.ATTACK.getButton(),
this.client.crosshairTarget.getType() == HitResult.Type.BLOCK ? "lambdacontrols.action.hit" : ButtonBinding.ATTACK.getTranslationKey(),
this.client.crosshairTarget.getType() != HitResult.Type.MISS);
} }
} }
public void renderFirstIcons(MatrixStack matrices, int x, int y)
{
int offset = 2 + this.inventoryWidth + this.inventoryButtonWidth + 4;
int currentX = this.mod.config.getHudSide() == HudSide.LEFT ? x : x - this.inventoryButtonWidth;
this.drawButton(matrices, currentX, y, ButtonBinding.INVENTORY, true);
this.drawButton(matrices, currentX += (this.mod.config.getHudSide() == HudSide.LEFT ? offset : -offset), y, ButtonBinding.SWAP_HANDS, true);
offset = 2 + this.swapHandsWidth + this.dropItemButtonWidth + 4;
if (this.client.options.showSubtitles && this.mod.config.getHudSide() == HudSide.RIGHT) {
currentX += -offset;
} else {
currentX = this.mod.config.getHudSide() == HudSide.LEFT ? x : x - this.dropItemButtonWidth;
y -= 24;
}
this.drawButton(matrices, currentX, y, ButtonBinding.DROP_ITEM, !this.client.player.getMainHandStack().isEmpty());
}
public void renderSecondIcons(MatrixStack matrices, int x, int y)
{
int offset;
int currentX = x;
if (!this.placeAction.isEmpty()) {
if (this.mod.config.getHudSide() == HudSide.LEFT)
currentX -= this.useButtonWidth;
this.drawButton(matrices, currentX, y, ButtonBinding.USE, true);
offset = 2 + this.useWidth + 4;
if (this.client.options.showSubtitles && this.mod.config.getHudSide() == HudSide.LEFT) {
currentX -= offset;
} else {
currentX = x;
y -= 24;
}
}
if (this.mod.config.getHudSide() == HudSide.LEFT)
currentX -= this.attackButtonWidth;
this.drawButton(matrices, currentX, y, ButtonBinding.ATTACK, this.attackWidth != 0);
}
public void renderFirstSection(MatrixStack matrices, int x, int y)
{
int currentX = this.mod.config.getHudSide() == HudSide.LEFT ? x + this.inventoryButtonWidth + 2 : x - this.inventoryButtonWidth - 2 - this.inventoryWidth;
this.drawTip(matrices, currentX, y, ButtonBinding.INVENTORY, true);
currentX += this.mod.config.getHudSide() == HudSide.LEFT ? this.inventoryWidth + 4 + this.swapHandsButtonWidth + 2
: -this.swapHandsWidth - 2 - this.swapHandsButtonWidth - 4;
this.drawTip(matrices, currentX, y, ButtonBinding.SWAP_HANDS, true);
if (this.client.options.showSubtitles && this.mod.config.getHudSide() == HudSide.RIGHT) {
currentX += -this.dropItemWidth - 2 - this.dropItemButtonWidth - 4;
} else {
y -= 24;
currentX = this.mod.config.getHudSide() == HudSide.LEFT ? x + this.dropItemButtonWidth + 2 : x - this.dropItemButtonWidth - 2 - this.dropItemWidth;
}
this.drawTip(matrices, currentX, y, ButtonBinding.DROP_ITEM, !this.client.player.getMainHandStack().isEmpty());
}
public void renderSecondSection(MatrixStack matrices, int x, int y)
{
int currentX = x;
if (!this.placeAction.isEmpty()) {
currentX += this.mod.config.getHudSide() == HudSide.RIGHT ? this.useButtonWidth + 2 : -this.useButtonWidth - 2 - this.useWidth;
this.drawTip(matrices, currentX, y, this.placeAction, true);
if (this.client.options.showSubtitles && this.mod.config.getHudSide() == HudSide.LEFT) {
currentX -= 4;
} else {
currentX = x;
y -= 24;
}
}
currentX += this.mod.config.getHudSide() == HudSide.RIGHT ? this.attackButtonWidth + 2 : -this.attackButtonWidth - 2 - this.attackWidth;
this.drawTip(matrices, currentX, y, this.attackAction, this.attackWidth != 0);
}
@Override
public void tick()
{
super.tick();
if (this.mod.config.getControlsMode() == ControlsMode.CONTROLLER) {
if (this.client.crosshairTarget == null)
return;
String placeAction;
// Update "Use" tip status.
if (this.client.crosshairTarget.getType() == HitResult.Type.MISS) {
this.placeHitResult = LambdaInput.tryFrontPlace(this.client);
this.attackAction = "";
this.attackWidth = 0;
} else {
if (this.client.crosshairTarget.getType() == HitResult.Type.BLOCK)
this.placeHitResult = (BlockHitResult) this.client.crosshairTarget;
else
this.placeHitResult = null;
this.attackAction = this.client.crosshairTarget.getType() == HitResult.Type.BLOCK ? "lambdacontrols.action.hit" : ButtonBinding.ATTACK.getTranslationKey();
this.attackWidth = this.width(attackAction);
}
ItemStack stack = this.client.player.getMainHandStack();
if ((stack == null || stack.isEmpty()) && ((stack = this.client.player.getOffHandStack()) == null || stack.isEmpty())) {
placeAction = "";
} else {
if (this.placeHitResult != null && stack.getItem() instanceof BlockItem) {
placeAction = "lambdacontrols.action.place";
} else {
placeAction = ButtonBinding.USE.getTranslationKey();
}
}
this.placeAction = placeAction;
// Cache the "Use" tip width.
if (this.placeAction.isEmpty())
this.useWidth = 0;
else
this.useWidth = this.width(this.placeAction);
}
}
@Override
public boolean hasTicks()
{
return true;
}
private int bottom(int y) private int bottom(int y)
{ {
return this.client.getWindow().getScaledHeight() - y - 15; return this.client.getWindow().getScaledHeight() - y - LambdaControlsRenderer.ICON_SIZE;
} }
private int drawButtonTip(int x, int y, @NotNull ButtonBinding button, boolean display) private int width(@NotNull ButtonBinding binding)
{ {
return LambdaControlsClient.drawButtonTip(x, y, button, display, this.client); return this.width(binding.getTranslationKey());
} }
private int drawButtonTip(int x, int y, int[] button, @NotNull String action, boolean display) private int width(@Nullable String text)
{ {
return LambdaControlsClient.drawButtonTip(x, y, button, action, display, this.client); if (text == null || text.isEmpty())
return 0;
return this.client.textRenderer.getWidth(I18n.translate(text));
}
private void drawButton(MatrixStack matrices, int x, int y, @NotNull ButtonBinding button, boolean display)
{
if (display)
LambdaControlsRenderer.drawButton(matrices, x, y, button, this.client);
}
private void drawTip(MatrixStack matrices, int x, int y, @NotNull ButtonBinding button, boolean display)
{
this.drawTip(matrices, x, y, button.getTranslationKey(), display);
}
private void drawTip(MatrixStack matrices, int x, int y, @NotNull String action, boolean display)
{
if (!display)
return;
String translatedAction = I18n.translate(action);
int textY = (LambdaControlsRenderer.ICON_SIZE / 2 - this.client.textRenderer.fontHeight / 2) + 1;
this.client.textRenderer.draw(matrices, translatedAction, (float) x, (float) (y + textY), 14737632);
} }
} }

View File

@@ -0,0 +1,280 @@
/*
* Copyright © 2020 LambdAurora <aurora42lambda@gmail.com>
*
* This file is part of LambdaControls.
*
* Licensed under the MIT license. For more information,
* see the LICENSE file.
*/
package me.lambdaurora.lambdacontrols.client.gui;
import com.mojang.blaze3d.systems.RenderSystem;
import me.lambdaurora.lambdacontrols.client.LambdaControlsClient;
import me.lambdaurora.lambdacontrols.client.controller.ButtonBinding;
import me.lambdaurora.lambdacontrols.client.util.HandledScreenAccessor;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.DrawableHelper;
import net.minecraft.client.gui.screen.ingame.HandledScreen;
import net.minecraft.client.resource.language.I18n;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.screen.slot.Slot;
import org.aperlambda.lambdacommon.utils.Pair;
import org.jetbrains.annotations.NotNull;
import org.lwjgl.glfw.GLFW;
/**
* Represents the LambdaControls renderer.
*
* @author LambdAurora
* @version 1.3.1
* @since 1.2.0
*/
public class LambdaControlsRenderer
{
public static final int ICON_SIZE = 20;
private static final int BUTTON_SIZE = 15;
private static final int AXIS_SIZE = 18;
public static int getButtonSize(int button)
{
switch (button) {
case -1:
return 0;
case GLFW.GLFW_GAMEPAD_AXIS_LEFT_X + 100:
case GLFW.GLFW_GAMEPAD_AXIS_LEFT_X + 200:
case GLFW.GLFW_GAMEPAD_AXIS_LEFT_Y + 100:
case GLFW.GLFW_GAMEPAD_AXIS_LEFT_Y + 200:
case GLFW.GLFW_GAMEPAD_AXIS_RIGHT_X + 100:
case GLFW.GLFW_GAMEPAD_AXIS_RIGHT_X + 200:
case GLFW.GLFW_GAMEPAD_AXIS_RIGHT_Y + 100:
case GLFW.GLFW_GAMEPAD_AXIS_RIGHT_Y + 200:
return AXIS_SIZE;
default:
return BUTTON_SIZE;
}
}
/**
* Gets the binding icon width.
*
* @param binding The binding.
* @return The width.
*/
public static int getBindingIconWidth(@NotNull ButtonBinding binding)
{
return getBindingIconWidth(binding.getButton());
}
/**
* Gets the binding icon width.
*
* @param buttons The buttons.
* @return The width.
*/
public static int getBindingIconWidth(int[] buttons)
{
int width = 0;
for (int i = 0; i < buttons.length; i++) {
width += ICON_SIZE;
if (i + 1 < buttons.length) {
width += 2;
}
}
return width;
}
public static Pair<Integer, Integer> drawButton(MatrixStack matrices, int x, int y, @NotNull ButtonBinding button, @NotNull MinecraftClient client)
{
return drawButton(matrices, x, y, button.getButton(), client);
}
public static Pair<Integer, Integer> drawButton(MatrixStack matrices, int x, int y, int[] buttons, @NotNull MinecraftClient client)
{
int height = 0;
int length = 0;
int currentX = x;
for (int i = 0; i < buttons.length; i++) {
int btn = buttons[i];
int size = drawButton(matrices, currentX, y, btn, client);
if (size > height)
height = size;
length += size;
if (i + 1 < buttons.length) {
length += 2;
currentX = x + length;
}
}
return Pair.of(length, height);
}
@SuppressWarnings("deprecated")
public static int drawButton(MatrixStack matrices, int x, int y, int button, @NotNull MinecraftClient client)
{
boolean second = false;
if (button == -1)
return 0;
else if (button >= 500) {
button -= 1000;
second = true;
}
int controllerType = LambdaControlsClient.get().config.getControllerType().getId();
boolean axis = false;
int buttonOffset = button * 15;
switch (button) {
case GLFW.GLFW_GAMEPAD_BUTTON_LEFT_BUMPER:
buttonOffset = 7 * 15;
break;
case GLFW.GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER:
buttonOffset = 8 * 15;
break;
case GLFW.GLFW_GAMEPAD_BUTTON_BACK:
buttonOffset = 4 * 15;
break;
case GLFW.GLFW_GAMEPAD_BUTTON_START:
buttonOffset = 6 * 15;
break;
case GLFW.GLFW_GAMEPAD_BUTTON_GUIDE:
buttonOffset = 5 * 15;
break;
case GLFW.GLFW_GAMEPAD_BUTTON_LEFT_THUMB:
buttonOffset = 15 * 15;
break;
case GLFW.GLFW_GAMEPAD_BUTTON_RIGHT_THUMB:
buttonOffset = 16 * 15;
break;
case GLFW.GLFW_GAMEPAD_AXIS_LEFT_X + 100:
buttonOffset = 0;
axis = true;
break;
case GLFW.GLFW_GAMEPAD_AXIS_LEFT_Y + 100:
buttonOffset = 18;
axis = true;
break;
case GLFW.GLFW_GAMEPAD_AXIS_RIGHT_X + 100:
buttonOffset = 2 * 18;
axis = true;
break;
case GLFW.GLFW_GAMEPAD_AXIS_RIGHT_Y + 100:
buttonOffset = 3 * 18;
axis = true;
break;
case GLFW.GLFW_GAMEPAD_AXIS_LEFT_X + 200:
buttonOffset = 4 * 18;
axis = true;
break;
case GLFW.GLFW_GAMEPAD_AXIS_LEFT_Y + 200:
buttonOffset = 5 * 18;
axis = true;
break;
case GLFW.GLFW_GAMEPAD_AXIS_RIGHT_X + 200:
buttonOffset = 6 * 18;
axis = true;
break;
case GLFW.GLFW_GAMEPAD_AXIS_RIGHT_Y + 200:
buttonOffset = 7 * 18;
axis = true;
break;
case GLFW.GLFW_GAMEPAD_AXIS_LEFT_TRIGGER + 100:
case GLFW.GLFW_GAMEPAD_AXIS_LEFT_TRIGGER + 200:
buttonOffset = 9 * 15;
break;
case GLFW.GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER + 100:
case GLFW.GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER + 200:
buttonOffset = 10 * 15;
break;
}
client.getTextureManager().bindTexture(axis ? LambdaControlsClient.CONTROLLER_AXIS : LambdaControlsClient.CONTROLLER_BUTTONS);
RenderSystem.disableDepthTest();
int assetSize = axis ? AXIS_SIZE : BUTTON_SIZE;
RenderSystem.color4f(1.0F, second ? 0.0F : 1.0F, 1.0F, 1.0F);
DrawableHelper.drawTexture(matrices, x + (ICON_SIZE / 2 - assetSize / 2), y + (ICON_SIZE / 2 - assetSize / 2),
(float) buttonOffset, (float) (controllerType * (axis ? AXIS_SIZE : BUTTON_SIZE)),
assetSize, assetSize,
256, 256);
RenderSystem.enableDepthTest();
return ICON_SIZE;
}
public static int drawButtonTip(MatrixStack matrices, int x, int y, @NotNull ButtonBinding button, boolean display, @NotNull MinecraftClient client)
{
return drawButtonTip(matrices, x, y, button.getButton(), button.getTranslationKey(), display, client);
}
public static int drawButtonTip(MatrixStack matrices, int x, int y, int[] button, @NotNull String action, boolean display, @NotNull MinecraftClient client)
{
if (display) {
int buttonWidth = drawButton(matrices, x, y, button, client).key;
String translatedAction = I18n.translate(action);
int textY = (LambdaControlsRenderer.ICON_SIZE / 2 - client.textRenderer.fontHeight / 2) + 1;
return client.textRenderer.drawWithShadow(matrices, translatedAction, (float) (x + buttonWidth + 2), (float) (y + textY), 14737632);
}
return -10;
}
private static int getButtonTipWidth(@NotNull String action, @NotNull TextRenderer textRenderer)
{
return 15 + 5 + textRenderer.getWidth(action);
}
public static void renderVirtualCursor(@NotNull MatrixStack matrices, @NotNull MinecraftClient client)
{
if (!LambdaControlsClient.get().config.hasVirtualMouse() || client.currentScreen == null)
return;
int mouseX = (int) (client.mouse.getX() * (double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth());
int mouseY = (int) (client.mouse.getY() * (double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight());
boolean hoverSlot = false;
if (client.currentScreen instanceof HandledScreen) {
HandledScreenAccessor inventoryScreen = (HandledScreenAccessor) client.currentScreen;
int guiLeft = inventoryScreen.getX();
int guiTop = inventoryScreen.getY();
Slot slot = inventoryScreen.lambdacontrols_getSlotAt(mouseX, mouseY);
if (slot != null) {
mouseX = guiLeft + slot.x;
mouseY = guiTop + slot.y;
hoverSlot = true;
}
}
if (!hoverSlot) {
mouseX -= 8;
mouseY -= 8;
}
drawCursor(matrices, mouseX, mouseY, hoverSlot, client);
}
/**
* Draws the virtual cursor.
*
* @param matrices The matrix stack.
* @param x X coordinate.
* @param y Y coordinate.
* @param hoverSlot True if hovering a slot, else false.
* @param client The client instance.
*/
public static void drawCursor(@NotNull MatrixStack matrices, int x, int y, boolean hoverSlot, @NotNull MinecraftClient client)
{
client.getTextureManager().bindTexture(LambdaControlsClient.CURSOR_TEXTURE);
RenderSystem.disableDepthTest();
RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F);
DrawableHelper.drawTexture(matrices, x, y, hoverSlot ? 16.F : 0.F, LambdaControlsClient.get().config.getVirtualMouseSkin().ordinal() * 16.F, 16, 16, 32, 64);
RenderSystem.enableDepthTest();
}
}

View File

@@ -23,13 +23,14 @@ import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.screen.options.ControlsOptionsScreen; import net.minecraft.client.gui.screen.options.ControlsOptionsScreen;
import net.minecraft.client.gui.widget.ButtonListWidget; import net.minecraft.client.gui.widget.ButtonListWidget;
import net.minecraft.client.gui.widget.ButtonWidget; import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.client.options.GameOptions;
import net.minecraft.client.options.Option; import net.minecraft.client.options.Option;
import net.minecraft.client.resource.language.I18n; import net.minecraft.client.resource.language.I18n;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.text.LiteralText;
import net.minecraft.text.MutableText;
import net.minecraft.text.TranslatableText; import net.minecraft.text.TranslatableText;
import net.minecraft.util.Formatting; import net.minecraft.util.Formatting;
import net.minecraft.util.Util; import net.minecraft.util.Util;
import org.jetbrains.annotations.NotNull;
import org.lwjgl.glfw.GLFW; import org.lwjgl.glfw.GLFW;
/** /**
@@ -37,7 +38,7 @@ import org.lwjgl.glfw.GLFW;
*/ */
public class LambdaControlsSettingsScreen extends Screen public class LambdaControlsSettingsScreen extends Screen
{ {
public static final String GAMEPAD_TOOL_URL = "http://generalarcade.com/gamepadtool/"; public static final String GAMEPAD_TOOL_URL = "https://generalarcade.com/gamepadtool/";
final LambdaControlsClient mod; final LambdaControlsClient mod;
private final Screen parent; private final Screen parent;
private final boolean hideControls; private final boolean hideControls;
@@ -47,6 +48,8 @@ public class LambdaControlsSettingsScreen extends Screen
private final Option mouseSpeedOption; private final Option mouseSpeedOption;
private final Option resetOption; private final Option resetOption;
// Gameplay options // Gameplay options
private final Option autoJumpOption;
private final Option fastBlockPlacingOption;
private final Option frontBlockPlacingOption; private final Option frontBlockPlacingOption;
private final Option flyDriftingOption; private final Option flyDriftingOption;
private final Option flyVerticalDriftingOption; private final Option flyVerticalDriftingOption;
@@ -58,14 +61,18 @@ public class LambdaControlsSettingsScreen extends Screen
private final Option invertsRightXAxis; private final Option invertsRightXAxis;
private final Option invertsRightYAxis; private final Option invertsRightYAxis;
private final Option unfocusedInputOption; private final Option unfocusedInputOption;
private final Option virtualMouseOption;
private final Option virtualMouseSkinOption;
// Hud options // Hud options
private final Option hudEnableOption; private final Option hudEnableOption;
private final Option hudSideOption; private final Option hudSideOption;
private final String controllerMappingsUrlText = I18n.translate("lambdacontrols.controller.mappings.2", Formatting.GOLD.toString(), GAMEPAD_TOOL_URL, Formatting.RESET.toString()); private final MutableText controllerMappingsUrlText = new LiteralText("(")
.append(new LiteralText(GAMEPAD_TOOL_URL).formatted(Formatting.GOLD))
.append("),");
private ButtonListWidget list; private ButtonListWidget list;
private SpruceLabelWidget gamepadToolUrlLabel; private SpruceLabelWidget gamepadToolUrlLabel;
public LambdaControlsSettingsScreen(Screen parent, @NotNull GameOptions options, boolean hideControls) public LambdaControlsSettingsScreen(Screen parent, boolean hideControls)
{ {
super(new TranslatableText("lambdacontrols.title.settings")); super(new TranslatableText("lambdacontrols.title.settings"));
this.mod = LambdaControlsClient.get(); this.mod = LambdaControlsClient.get();
@@ -74,19 +81,19 @@ public class LambdaControlsSettingsScreen extends Screen
// General options // General options
this.autoSwitchModeOption = new SpruceBooleanOption("lambdacontrols.menu.auto_switch_mode", this.mod.config::hasAutoSwitchMode, this.autoSwitchModeOption = new SpruceBooleanOption("lambdacontrols.menu.auto_switch_mode", this.mod.config::hasAutoSwitchMode,
this.mod.config::setAutoSwitchMode, new TranslatableText("lambdacontrols.tooltip.auto_switch_mode"), true); this.mod.config::setAutoSwitchMode, new TranslatableText("lambdacontrols.tooltip.auto_switch_mode"), true);
this.rotationSpeedOption = new SpruceDoubleOption("lambdacontrols.menu.rotation_speed", 0.0, 150.0, 0.5F, this.mod.config::getRotationSpeed, this.rotationSpeedOption = new SpruceDoubleOption("lambdacontrols.menu.rotation_speed", 0.0, 100.0, 0.5F, this.mod.config::getRotationSpeed,
newValue -> { newValue -> {
synchronized (this.mod.config) { synchronized (this.mod.config) {
this.mod.config.setRotationSpeed(newValue); this.mod.config.setRotationSpeed(newValue);
} }
}, option -> option.getDisplayPrefix() + option.get(), }, option -> option.getDisplayPrefix().append(String.valueOf(option.get())),
new TranslatableText("lambdacontrols.tooltip.rotation_speed")); new TranslatableText("lambdacontrols.tooltip.rotation_speed"));
this.mouseSpeedOption = new SpruceDoubleOption("lambdacontrols.menu.mouse_speed", 0.0, 150.0, 0.5F, this.mod.config::getMouseSpeed, this.mouseSpeedOption = new SpruceDoubleOption("lambdacontrols.menu.mouse_speed", 0.0, 150.0, 0.5F, this.mod.config::getMouseSpeed,
newValue -> { newValue -> {
synchronized (this.mod.config) { synchronized (this.mod.config) {
this.mod.config.setMouseSpeed(newValue); this.mod.config.setMouseSpeed(newValue);
} }
}, option -> option.getDisplayPrefix() + option.get(), }, option -> option.getDisplayPrefix().append(String.valueOf(option.get())),
new TranslatableText("lambdacontrols.tooltip.mouse_speed")); new TranslatableText("lambdacontrols.tooltip.mouse_speed"));
this.resetOption = new SpruceResetOption(btn -> { this.resetOption = new SpruceResetOption(btn -> {
this.mod.config.reset(); this.mod.config.reset();
@@ -94,6 +101,9 @@ public class LambdaControlsSettingsScreen extends Screen
this.init(client, client.getWindow().getScaledWidth(), client.getWindow().getScaledHeight()); this.init(client, client.getWindow().getScaledWidth(), client.getWindow().getScaledHeight());
}); });
// Gameplay options // Gameplay options
this.autoJumpOption = SpruceBooleanOption.fromVanilla("options.autoJump", Option.AUTO_JUMP, null, true);
this.fastBlockPlacingOption = new SpruceBooleanOption("lambdacontrols.menu.fast_block_placing", this.mod.config::hasFastBlockPlacing,
this.mod.config::setFastBlockPlacing, new TranslatableText("lambdacontrols.tooltip.fast_block_placing"), true);
this.frontBlockPlacingOption = new SpruceBooleanOption("lambdacontrols.menu.front_block_placing", this.mod.config::hasFrontBlockPlacing, this.frontBlockPlacingOption = new SpruceBooleanOption("lambdacontrols.menu.front_block_placing", this.mod.config::hasFrontBlockPlacing,
this.mod.config::setFrontBlockPlacing, new TranslatableText("lambdacontrols.tooltip.front_block_placing"), true); this.mod.config::setFrontBlockPlacing, new TranslatableText("lambdacontrols.tooltip.front_block_placing"), true);
this.flyDriftingOption = new SpruceBooleanOption("lambdacontrols.menu.fly_drifting", this.mod.config::hasFlyDrifting, this.flyDriftingOption = new SpruceBooleanOption("lambdacontrols.menu.fly_drifting", this.mod.config::hasFlyDrifting,
@@ -110,11 +120,11 @@ public class LambdaControlsSettingsScreen extends Screen
}, option -> { }, option -> {
String controllerName = this.mod.config.getController().getName(); String controllerName = this.mod.config.getController().getName();
if (!this.mod.config.getController().isConnected()) if (!this.mod.config.getController().isConnected())
return option.getDisplayPrefix() + Formatting.RED + controllerName; return option.getDisplayPrefix().append(new LiteralText(controllerName).formatted(Formatting.RED));
else if (!this.mod.config.getController().isGamepad()) else if (!this.mod.config.getController().isGamepad())
return option.getDisplayPrefix() + Formatting.GOLD + controllerName; return option.getDisplayPrefix().append(new LiteralText(controllerName).formatted(Formatting.GOLD));
else else
return option.getDisplayPrefix() + controllerName; return option.getDisplayPrefix().append(controllerName);
}, null); }, null);
this.secondControllerOption = new SpruceCyclingOption("lambdacontrols.menu.controller2", this.secondControllerOption = new SpruceCyclingOption("lambdacontrols.menu.controller2",
amount -> { amount -> {
@@ -126,16 +136,16 @@ public class LambdaControlsSettingsScreen extends Screen
}, option -> this.mod.config.getSecondController().map(controller -> { }, option -> this.mod.config.getSecondController().map(controller -> {
String controllerName = controller.getName(); String controllerName = controller.getName();
if (!controller.isConnected()) if (!controller.isConnected())
return option.getDisplayPrefix() + Formatting.RED + controllerName; return option.getDisplayPrefix().append(new LiteralText(controllerName).formatted(Formatting.RED));
else if (!controller.isGamepad()) else if (!controller.isGamepad())
return option.getDisplayPrefix() + Formatting.GOLD + controllerName; return option.getDisplayPrefix().append(new LiteralText(controllerName).formatted(Formatting.GOLD));
else else
return option.getDisplayPrefix() + controllerName; return option.getDisplayPrefix().append(controllerName);
}).orElse(option.getDisplayPrefix() + Formatting.RED + I18n.translate("options.off")), }).orElse(option.getDisplayPrefix().append(new TranslatableText("options.off").formatted(Formatting.RED))),
new TranslatableText("lambdacontrols.tooltip.controller2")); new TranslatableText("lambdacontrols.tooltip.controller2"));
this.controllerTypeOption = new SpruceCyclingOption("lambdacontrols.menu.controller_type", this.controllerTypeOption = new SpruceCyclingOption("lambdacontrols.menu.controller_type",
amount -> this.mod.config.setControllerType(this.mod.config.getControllerType().next()), amount -> this.mod.config.setControllerType(this.mod.config.getControllerType().next()),
option -> option.getDisplayPrefix() + this.mod.config.getControllerType().getTranslatedName(), option -> option.getDisplayPrefix().append(this.mod.config.getControllerType().getTranslatedName()),
new TranslatableText("lambdacontrols.tooltip.controller_type")); new TranslatableText("lambdacontrols.tooltip.controller_type"));
this.deadZoneOption = new SpruceDoubleOption("lambdacontrols.menu.dead_zone", 0.05, 1.0, 0.05F, this.mod.config::getDeadZone, this.deadZoneOption = new SpruceDoubleOption("lambdacontrols.menu.dead_zone", 0.05, 1.0, 0.05F, this.mod.config::getDeadZone,
newValue -> { newValue -> {
@@ -144,7 +154,7 @@ public class LambdaControlsSettingsScreen extends Screen
} }
}, option -> { }, option -> {
String value = String.valueOf(option.get()); String value = String.valueOf(option.get());
return option.getDisplayPrefix() + value.substring(0, Math.min(value.length(), 5)); return option.getDisplayPrefix().append(value.substring(0, Math.min(value.length(), 5)));
}, new TranslatableText("lambdacontrols.tooltip.dead_zone")); }, new TranslatableText("lambdacontrols.tooltip.dead_zone"));
this.invertsRightXAxis = new SpruceBooleanOption("lambdacontrols.menu.invert_right_x_axis", this.mod.config::doesInvertRightXAxis, this.invertsRightXAxis = new SpruceBooleanOption("lambdacontrols.menu.invert_right_x_axis", this.mod.config::doesInvertRightXAxis,
newValue -> { newValue -> {
@@ -160,12 +170,18 @@ public class LambdaControlsSettingsScreen extends Screen
}, null, true); }, null, true);
this.unfocusedInputOption = new SpruceBooleanOption("lambdacontrols.menu.unfocused_input", this.mod.config::hasUnfocusedInput, this.unfocusedInputOption = new SpruceBooleanOption("lambdacontrols.menu.unfocused_input", this.mod.config::hasUnfocusedInput,
this.mod.config::setUnfocusedInput, new TranslatableText("lambdacontrols.tooltip.unfocused_input"), true); this.mod.config::setUnfocusedInput, new TranslatableText("lambdacontrols.tooltip.unfocused_input"), true);
this.virtualMouseOption = new SpruceBooleanOption("lambdacontrols.menu.virtual_mouse", this.mod.config::hasVirtualMouse,
this.mod.config::setVirtualMouse, new TranslatableText("lambdacontrols.tooltip.virtual_mouse"), true);
this.virtualMouseSkinOption = new SpruceCyclingOption("lambdacontrols.menu.virtual_mouse.skin",
amount -> this.mod.config.setVirtualMouseSkin(this.mod.config.getVirtualMouseSkin().next()),
option -> option.getDisplayPrefix().append(this.mod.config.getVirtualMouseSkin().getTranslatedName()),
null);
// HUD options // HUD options
this.hudEnableOption = new SpruceBooleanOption("lambdacontrols.menu.hud_enable", this.mod.config::isHudEnabled, this.hudEnableOption = new SpruceBooleanOption("lambdacontrols.menu.hud_enable", this.mod.config::isHudEnabled,
this.mod::setHudEnabled, new TranslatableText("lambdacontrols.tooltip.hud_enable"), true); this.mod::setHudEnabled, new TranslatableText("lambdacontrols.tooltip.hud_enable"), true);
this.hudSideOption = new SpruceCyclingOption("lambdacontrols.menu.hud_side", this.hudSideOption = new SpruceCyclingOption("lambdacontrols.menu.hud_side",
amount -> this.mod.config.setHudSide(this.mod.config.getHudSide().next()), amount -> this.mod.config.setHudSide(this.mod.config.getHudSide().next()),
option -> option.getDisplayPrefix() + this.mod.config.getHudSide().getTranslatedName(), option -> option.getDisplayPrefix().append(this.mod.config.getHudSide().getTranslatedName()),
new TranslatableText("lambdacontrols.tooltip.hud_side")); new TranslatableText("lambdacontrols.tooltip.hud_side"));
} }
@@ -185,7 +201,7 @@ public class LambdaControlsSettingsScreen extends Screen
private int getTextHeight() private int getTextHeight()
{ {
return (5 + this.font.fontHeight) * 3 + 5; return (5 + this.textRenderer.fontHeight) * 3 + 5;
} }
@Override @Override
@@ -194,36 +210,37 @@ public class LambdaControlsSettingsScreen extends Screen
super.init(); super.init();
int buttonHeight = 20; int buttonHeight = 20;
SpruceButtonWidget controlsModeBtn = new SpruceButtonWidget(this.width / 2 - 155, 18, this.hideControls ? 310 : 150, buttonHeight, SpruceButtonWidget controlsModeBtn = new SpruceButtonWidget(this.width / 2 - 155, 18, this.hideControls ? 310 : 150, buttonHeight,
I18n.translate("lambdacontrols.menu.controls_mode") + ": " + I18n.translate(this.mod.config.getControlsMode().getTranslationKey()), new TranslatableText("lambdacontrols.menu.controls_mode").append(": ").append(new TranslatableText(this.mod.config.getControlsMode().getTranslationKey())),
btn -> { btn -> {
ControlsMode next = this.mod.config.getControlsMode().next(); ControlsMode next = this.mod.config.getControlsMode().next();
btn.setMessage(I18n.translate("lambdacontrols.menu.controls_mode") + ": " + I18n.translate(next.getTranslationKey())); btn.setMessage(new TranslatableText("lambdacontrols.menu.controls_mode").append(": ").append(new TranslatableText(next.getTranslationKey())));
this.mod.config.setControlsMode(next); this.mod.config.setControlsMode(next);
this.mod.config.save(); this.mod.config.save();
if (this.minecraft.player != null) { if (this.client.player != null) {
ClientSidePacketRegistry.INSTANCE.sendToServer(LambdaControls.CONTROLS_MODE_CHANNEL, this.mod.makeControlsModeBuffer(next)); ClientSidePacketRegistry.INSTANCE.sendToServer(LambdaControls.CONTROLS_MODE_CHANNEL, this.mod.makeControlsModeBuffer(next));
} }
}); });
controlsModeBtn.setTooltip(new TranslatableText("lambdacontrols.tooltip.controls_mode")); controlsModeBtn.setTooltip(new TranslatableText("lambdacontrols.tooltip.controls_mode"));
this.addButton(controlsModeBtn); this.addButton(controlsModeBtn);
if (!this.hideControls) if (!this.hideControls)
this.addButton(new ButtonWidget(this.width / 2 - 155 + 160, 18, 150, buttonHeight, I18n.translate("options.controls"), this.addButton(new ButtonWidget(this.width / 2 - 155 + 160, 18, 150, buttonHeight, new TranslatableText("options.controls"),
btn -> { btn -> {
if (this.mod.config.getControlsMode() == ControlsMode.CONTROLLER) if (this.mod.config.getControlsMode() == ControlsMode.CONTROLLER)
this.minecraft.openScreen(new ControllerControlsScreen(this, true)); this.client.openScreen(new ControllerControlsScreen(this, true));
else else
this.minecraft.openScreen(new ControlsOptionsScreen(this, this.minecraft.options)); this.client.openScreen(new ControlsOptionsScreen(this, this.client.options));
})); }));
this.list = new ButtonListWidget(this.minecraft, this.width, this.height, 43, this.height - 29 - this.getTextHeight(), 25); this.list = new ButtonListWidget(this.client, this.width, this.height, 43, this.height - 29 - this.getTextHeight(), 25);
// General options // General options
this.list.addSingleOptionEntry(new SpruceSeparatorOption("lambdacontrols.menu.title.general", true, null)); this.list.addSingleOptionEntry(new SpruceSeparatorOption("lambdacontrols.menu.title.general", true, null));
this.list.addOptionEntry(this.rotationSpeedOption, this.mouseSpeedOption); this.list.addOptionEntry(this.rotationSpeedOption, this.mouseSpeedOption);
this.list.addSingleOptionEntry(this.autoSwitchModeOption); this.list.addSingleOptionEntry(this.autoSwitchModeOption);
// Gameplay options // Gameplay options
this.list.addSingleOptionEntry(new SpruceSeparatorOption("lambdacontrols.menu.title.gameplay", true, null)); this.list.addSingleOptionEntry(new SpruceSeparatorOption("lambdacontrols.menu.title.gameplay", true, null));
this.list.addSingleOptionEntry(this.frontBlockPlacingOption); this.list.addSingleOptionEntry(this.autoJumpOption);
this.list.addOptionEntry(this.fastBlockPlacingOption, this.frontBlockPlacingOption);
this.list.addSingleOptionEntry(this.flyDriftingOption); this.list.addSingleOptionEntry(this.flyDriftingOption);
this.list.addSingleOptionEntry(this.flyVerticalDriftingOption); this.list.addSingleOptionEntry(this.flyVerticalDriftingOption);
// Controller options // Controller options
@@ -232,34 +249,35 @@ public class LambdaControlsSettingsScreen extends Screen
this.list.addSingleOptionEntry(this.secondControllerOption); this.list.addSingleOptionEntry(this.secondControllerOption);
this.list.addOptionEntry(this.controllerTypeOption, this.deadZoneOption); this.list.addOptionEntry(this.controllerTypeOption, this.deadZoneOption);
this.list.addOptionEntry(this.invertsRightXAxis, this.invertsRightYAxis); this.list.addOptionEntry(this.invertsRightXAxis, this.invertsRightYAxis);
this.list.addSingleOptionEntry(this.unfocusedInputOption); this.list.addOptionEntry(this.unfocusedInputOption, this.virtualMouseOption);
this.list.addSingleOptionEntry(this.virtualMouseSkinOption);
this.list.addSingleOptionEntry(new ReloadControllerMappingsOption()); this.list.addSingleOptionEntry(new ReloadControllerMappingsOption());
// HUD options // HUD options
this.list.addSingleOptionEntry(new SpruceSeparatorOption("lambdacontrols.menu.title.hud", true, null)); this.list.addSingleOptionEntry(new SpruceSeparatorOption("lambdacontrols.menu.title.hud", true, null));
this.list.addOptionEntry(this.hudEnableOption, this.hudSideOption); this.list.addOptionEntry(this.hudEnableOption, this.hudSideOption);
this.children.add(this.list); this.children.add(this.list);
this.gamepadToolUrlLabel = new SpruceLabelWidget(this.width / 2, this.height - 29 - (5 + this.font.fontHeight) * 2, this.controllerMappingsUrlText, this.width, this.gamepadToolUrlLabel = new SpruceLabelWidget(this.width / 2, this.height - 29 - (5 + this.textRenderer.fontHeight) * 2, this.controllerMappingsUrlText, this.width,
label -> Util.getOperatingSystem().open(GAMEPAD_TOOL_URL), true); label -> Util.getOperatingSystem().open(GAMEPAD_TOOL_URL), true);
this.gamepadToolUrlLabel.setTooltip(new TranslatableText("chat.link.open")); this.gamepadToolUrlLabel.setTooltip(new TranslatableText("chat.link.open"));
this.children.add(this.gamepadToolUrlLabel); this.children.add(this.gamepadToolUrlLabel);
this.addButton(this.resetOption.createButton(this.minecraft.options, this.width / 2 - 155, this.height - 29, 150)); this.addButton(this.resetOption.createButton(this.client.options, this.width / 2 - 155, this.height - 29, 150));
this.addButton(new ButtonWidget(this.width / 2 - 155 + 160, this.height - 29, 150, buttonHeight, I18n.translate("gui.done"), this.addButton(new ButtonWidget(this.width / 2 - 155 + 160, this.height - 29, 150, buttonHeight, new TranslatableText("gui.done"),
(buttonWidget) -> this.minecraft.openScreen(this.parent))); (buttonWidget) -> this.client.openScreen(this.parent)));
} }
@Override @Override
public void render(int mouseX, int mouseY, float delta) public void render(MatrixStack matrices, int mouseX, int mouseY, float delta)
{ {
this.renderBackground(); this.renderBackground(matrices);
this.list.render(mouseX, mouseY, delta); this.list.render(matrices, mouseX, mouseY, delta);
super.render(mouseX, mouseY, delta); super.render(matrices, mouseX, mouseY, delta);
this.drawCenteredString(this.font, I18n.translate("lambdacontrols.menu.title"), this.width / 2, 8, 16777215); this.drawCenteredString(matrices, this.textRenderer, I18n.translate("lambdacontrols.menu.title"), this.width / 2, 8, 16777215);
this.drawCenteredString(this.font, I18n.translate("lambdacontrols.controller.mappings.1", Formatting.GREEN.toString(), Formatting.RESET.toString()), this.width / 2, this.height - 29 - (5 + this.font.fontHeight) * 3, 10526880); this.drawCenteredString(matrices, this.textRenderer, I18n.translate("lambdacontrols.controller.mappings.1", Formatting.GREEN.toString(), Formatting.RESET.toString()), this.width / 2, this.height - 29 - (5 + this.textRenderer.fontHeight) * 3, 10526880);
this.gamepadToolUrlLabel.render(mouseX, mouseY, delta); this.gamepadToolUrlLabel.render(matrices, mouseX, mouseY, delta);
this.drawCenteredString(this.font, I18n.translate("lambdacontrols.controller.mappings.3", Formatting.GREEN.toString(), Formatting.RESET.toString()), this.width / 2, this.height - 29 - (5 + this.font.fontHeight), 10526880); this.drawCenteredString(matrices, this.textRenderer, I18n.translate("lambdacontrols.controller.mappings.3", Formatting.GREEN.toString(), Formatting.RESET.toString()), this.width / 2, this.height - 29 - (5 + this.textRenderer.fontHeight), 10526880);
Tooltip.renderAll(); Tooltip.renderAll(matrices);
} }
} }

View File

@@ -36,7 +36,7 @@ public class ReloadControllerMappingsOption extends Option implements Nameable
@Override @Override
public AbstractButtonWidget createButton(GameOptions options, int x, int y, int width) public AbstractButtonWidget createButton(GameOptions options, int x, int y, int width)
{ {
SpruceButtonWidget button = new SpruceButtonWidget(x, y, width, 20, this.getName(), btn -> { SpruceButtonWidget button = new SpruceButtonWidget(x, y, width, 20, new TranslatableText(KEY), btn -> {
MinecraftClient client = MinecraftClient.getInstance(); MinecraftClient client = MinecraftClient.getInstance();
Controller.updateMappings(); Controller.updateMappings();
if (client.currentScreen != null) if (client.currentScreen != null)

View File

@@ -19,7 +19,7 @@ import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.screen.ingame.InventoryScreen; import net.minecraft.client.gui.screen.ingame.InventoryScreen;
import net.minecraft.client.gui.widget.ButtonWidget; import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.client.gui.widget.TexturedButtonWidget; import net.minecraft.client.gui.widget.TexturedButtonWidget;
import net.minecraft.server.network.packet.PlayerActionC2SPacket; import net.minecraft.network.packet.c2s.play.PlayerActionC2SPacket;
import net.minecraft.text.LiteralText; import net.minecraft.text.LiteralText;
import net.minecraft.util.Arm; import net.minecraft.util.Arm;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
@@ -70,14 +70,14 @@ public class TouchscreenOverlay extends Screen
private void pauseGame(boolean bl) private void pauseGame(boolean bl)
{ {
if (this.minecraft == null) if (this.client == null)
return; return;
boolean bl2 = this.minecraft.isIntegratedServerRunning() && !this.minecraft.getServer().isRemote(); boolean bl2 = this.client.isIntegratedServerRunning() && !this.client.getServer().isRemote();
if (bl2) { if (bl2) {
this.minecraft.openScreen(new GameMenuScreen(!bl)); this.client.openScreen(new GameMenuScreen(!bl));
this.minecraft.getSoundManager().pauseAll(); this.client.getSoundManager().pauseAll();
} else { } else {
this.minecraft.openScreen(new GameMenuScreen(true)); this.client.openScreen(new GameMenuScreen(true));
} }
} }
@@ -99,9 +99,9 @@ public class TouchscreenOverlay extends Screen
*/ */
private void updateJumpButtons() private void updateJumpButtons()
{ {
if (this.minecraft == null) if (this.client == null)
return; return;
if (this.minecraft.player.abilities.allowFlying && this.minecraft.player.abilities.flying) { if (this.client.player.abilities.allowFlying && this.client.player.abilities.flying) {
boolean oldStateFly = this.flyButton.visible; boolean oldStateFly = this.flyButton.visible;
this.jumpButton.visible = false; this.jumpButton.visible = false;
this.flyButton.visible = true; this.flyButton.visible = true;
@@ -128,7 +128,7 @@ public class TouchscreenOverlay extends Screen
*/ */
private void handleJump(ButtonWidget btn, boolean state) private void handleJump(ButtonWidget btn, boolean state)
{ {
((KeyBindingAccessor) this.minecraft.options.keyJump).lambdacontrols_handlePressState(state); ((KeyBindingAccessor) this.client.options.keyJump).lambdacontrols_handlePressState(state);
} }
@Override @Override
@@ -149,27 +149,27 @@ public class TouchscreenOverlay extends Screen
protected void init() protected void init()
{ {
super.init(); super.init();
int scaledWidth = this.minecraft.getWindow().getScaledWidth(); int scaledWidth = this.client.getWindow().getScaledWidth();
int scaledHeight = this.minecraft.getWindow().getScaledHeight(); int scaledHeight = this.client.getWindow().getScaledHeight();
this.addButton(new TexturedButtonWidget(scaledWidth / 2 - 20, 0, 20, 20, 0, 106, 20, ButtonWidget.WIDGETS_LOCATION, 256, 256, this.addButton(new TexturedButtonWidget(scaledWidth / 2 - 20, 0, 20, 20, 0, 106, 20, ButtonWidget.WIDGETS_LOCATION, 256, 256,
btn -> this.minecraft.openScreen(new ChatScreen("")), "")); btn -> this.client.openScreen(new ChatScreen("")), LiteralText.EMPTY));
this.addButton(new TexturedButtonWidget(scaledWidth / 2, 0, 20, 20, 0, 0, 20, WIDGETS_LOCATION, 256, 256, this.addButton(new TexturedButtonWidget(scaledWidth / 2, 0, 20, 20, 0, 0, 20, WIDGETS_LOCATION, 256, 256,
btn -> this.pauseGame(false))); btn -> this.pauseGame(false)));
// Inventory buttons. // Inventory buttons.
int inventoryButtonX = scaledWidth / 2; int inventoryButtonX = scaledWidth / 2;
int inventoryButtonY = scaledHeight - 16 - 5; int inventoryButtonY = scaledHeight - 16 - 5;
if (this.minecraft.options.mainArm == Arm.LEFT) { if (this.client.options.mainArm == Arm.LEFT) {
inventoryButtonX = inventoryButtonX - 91 - 24; inventoryButtonX = inventoryButtonX - 91 - 24;
} else { } else {
inventoryButtonX = inventoryButtonX + 91 + 4; inventoryButtonX = inventoryButtonX + 91 + 4;
} }
this.addButton(new TexturedButtonWidget(inventoryButtonX, inventoryButtonY, 20, 20, 20, 0, 20, WIDGETS_LOCATION, 256, 256, this.addButton(new TexturedButtonWidget(inventoryButtonX, inventoryButtonY, 20, 20, 20, 0, 20, WIDGETS_LOCATION, 256, 256,
btn -> { btn -> {
if (this.minecraft.interactionManager.hasRidingInventory()) { if (this.client.interactionManager.hasRidingInventory()) {
this.minecraft.player.openRidingInventory(); this.client.player.openRidingInventory();
} else { } else {
this.minecraft.getTutorialManager().onInventoryOpened(); this.client.getTutorialManager().onInventoryOpened();
this.minecraft.openScreen(new InventoryScreen(this.minecraft.player)); this.client.openScreen(new InventoryScreen(this.client.player));
} }
})); }));
int jumpButtonX, swapHandsX, sneakButtonX; int jumpButtonX, swapHandsX, sneakButtonX;
@@ -187,31 +187,31 @@ public class TouchscreenOverlay extends Screen
this.addButton(new SpruceTexturedButtonWidget(swapHandsX, sneakButtonY, 20, 20, 0, 160, 20, WIDGETS_LOCATION, this.addButton(new SpruceTexturedButtonWidget(swapHandsX, sneakButtonY, 20, 20, 0, 160, 20, WIDGETS_LOCATION,
(btn, state) -> { (btn, state) -> {
if (state) { if (state) {
if (!this.minecraft.player.isSpectator()) { if (!this.client.player.isSpectator()) {
this.minecraft.getNetworkHandler().sendPacket(new PlayerActionC2SPacket(PlayerActionC2SPacket.Action.SWAP_HELD_ITEMS, BlockPos.ORIGIN, Direction.DOWN)); this.client.getNetworkHandler().sendPacket(new PlayerActionC2SPacket(PlayerActionC2SPacket.Action.SWAP_ITEM_WITH_OFFHAND, BlockPos.ORIGIN, Direction.DOWN));
} }
} }
})); }));
// Drop // Drop
this.addButton(new SpruceTexturedButtonWidget(swapHandsX, sneakButtonY + 5 + 20, 20, 20, 20, 160, 20, WIDGETS_LOCATION, this.addButton(new SpruceTexturedButtonWidget(swapHandsX, sneakButtonY + 5 + 20, 20, 20, 20, 160, 20, WIDGETS_LOCATION,
(btn, state) -> ((KeyBindingAccessor) this.minecraft.options.keyDrop).lambdacontrols_handlePressState(state))); (btn, state) -> ((KeyBindingAccessor) this.client.options.keyDrop).lambdacontrols_handlePressState(state)));
// Jump keys // Jump keys
this.addButton(this.jumpButton = new SpruceTexturedButtonWidget(jumpButtonX, sneakButtonY, 20, 20, 0, 40, 20, WIDGETS_LOCATION, this.addButton(this.jumpButton = new SpruceTexturedButtonWidget(jumpButtonX, sneakButtonY, 20, 20, 0, 40, 20, WIDGETS_LOCATION,
this::handleJump)); this::handleJump));
this.addButton(this.flyButton = new SpruceTexturedButtonWidget(jumpButtonX, sneakButtonY, 20, 20, 20, 40, 20, WIDGETS_LOCATION, this.addButton(this.flyButton = new SpruceTexturedButtonWidget(jumpButtonX, sneakButtonY, 20, 20, 20, 40, 20, WIDGETS_LOCATION,
(btn, state) -> { (btn, state) -> {
if (this.flyButtonEnableTicks == 0) this.minecraft.player.abilities.flying = false; if (this.flyButtonEnableTicks == 0) this.client.player.abilities.flying = false;
})); }));
this.addButton(this.flyUpButton = new SpruceTexturedButtonWidget(jumpButtonX, sneakButtonY - 5 - 20, 20, 20, 40, 40, 20, WIDGETS_LOCATION, this.addButton(this.flyUpButton = new SpruceTexturedButtonWidget(jumpButtonX, sneakButtonY - 5 - 20, 20, 20, 40, 40, 20, WIDGETS_LOCATION,
this::handleJump)); this::handleJump));
this.addButton(this.flyDownButton = new SpruceTexturedButtonWidget(jumpButtonX, sneakButtonY + 20 + 5, 20, 20, 60, 40, 20, WIDGETS_LOCATION, this.addButton(this.flyDownButton = new SpruceTexturedButtonWidget(jumpButtonX, sneakButtonY + 20 + 5, 20, 20, 60, 40, 20, WIDGETS_LOCATION,
(btn, state) -> ((KeyBindingAccessor) this.minecraft.options.keySneak).lambdacontrols_handlePressState(state))); (btn, state) -> ((KeyBindingAccessor) this.client.options.keySneak).lambdacontrols_handlePressState(state)));
this.updateJumpButtons(); this.updateJumpButtons();
// Movements keys // Movements keys
this.addButton((this.startSneakButton = new SpruceTexturedButtonWidget(sneakButtonX, sneakButtonY, 20, 20, 0, 120, 20, WIDGETS_LOCATION, this.addButton((this.startSneakButton = new SpruceTexturedButtonWidget(sneakButtonX, sneakButtonY, 20, 20, 0, 120, 20, WIDGETS_LOCATION,
(btn, state) -> { (btn, state) -> {
if (state) { if (state) {
((KeyBindingAccessor) this.minecraft.options.keySneak).lambdacontrols_handlePressState(true); ((KeyBindingAccessor) this.client.options.keySneak).lambdacontrols_handlePressState(true);
this.startSneakButton.visible = false; this.startSneakButton.visible = false;
this.endSneakButton.visible = true; this.endSneakButton.visible = true;
} }
@@ -219,7 +219,7 @@ public class TouchscreenOverlay extends Screen
this.addButton((this.endSneakButton = new SpruceTexturedButtonWidget(sneakButtonX, sneakButtonY, 20, 20, 20, 120, 20, WIDGETS_LOCATION, this.addButton((this.endSneakButton = new SpruceTexturedButtonWidget(sneakButtonX, sneakButtonY, 20, 20, 20, 120, 20, WIDGETS_LOCATION,
(btn, state) -> { (btn, state) -> {
if (state) { if (state) {
((KeyBindingAccessor) this.minecraft.options.keySneak).lambdacontrols_handlePressState(false); ((KeyBindingAccessor) this.client.options.keySneak).lambdacontrols_handlePressState(false);
this.endSneakButton.visible = false; this.endSneakButton.visible = false;
this.startSneakButton.visible = true; this.startSneakButton.visible = true;
} }
@@ -227,49 +227,49 @@ public class TouchscreenOverlay extends Screen
this.endSneakButton.visible = false; this.endSneakButton.visible = false;
this.addButton(this.forwardLeftButton = new SpruceTexturedButtonWidget(sneakButtonX - 20 - 5, sneakButtonY - 5 - 20, 20, 20, 80, 80, 20, WIDGETS_LOCATION, this.addButton(this.forwardLeftButton = new SpruceTexturedButtonWidget(sneakButtonX - 20 - 5, sneakButtonY - 5 - 20, 20, 20, 80, 80, 20, WIDGETS_LOCATION,
(btn, state) -> { (btn, state) -> {
((KeyBindingAccessor) this.minecraft.options.keyForward).lambdacontrols_handlePressState(state); ((KeyBindingAccessor) this.client.options.keyForward).lambdacontrols_handlePressState(state);
((KeyBindingAccessor) this.minecraft.options.keyLeft).lambdacontrols_handlePressState(state); ((KeyBindingAccessor) this.client.options.keyLeft).lambdacontrols_handlePressState(state);
this.updateForwardButtonsState(state); this.updateForwardButtonsState(state);
})); }));
this.forwardLeftButton.visible = false; this.forwardLeftButton.visible = false;
this.addButton(new SpruceTexturedButtonWidget(sneakButtonX, sneakButtonY - 5 - 20, 20, 20, 0, 80, 20, WIDGETS_LOCATION, this.addButton(new SpruceTexturedButtonWidget(sneakButtonX, sneakButtonY - 5 - 20, 20, 20, 0, 80, 20, WIDGETS_LOCATION,
(btn, state) -> { (btn, state) -> {
((KeyBindingAccessor) this.minecraft.options.keyForward).lambdacontrols_handlePressState(state); ((KeyBindingAccessor) this.client.options.keyForward).lambdacontrols_handlePressState(state);
this.updateForwardButtonsState(state); this.updateForwardButtonsState(state);
this.forwardLeftButton.visible = true; this.forwardLeftButton.visible = true;
this.forwardRightButton.visible = true; this.forwardRightButton.visible = true;
})); }));
this.addButton(this.forwardRightButton = new SpruceTexturedButtonWidget(sneakButtonX + 20 + 5, sneakButtonY - 5 - 20, 20, 20, 100, 80, 20, WIDGETS_LOCATION, this.addButton(this.forwardRightButton = new SpruceTexturedButtonWidget(sneakButtonX + 20 + 5, sneakButtonY - 5 - 20, 20, 20, 100, 80, 20, WIDGETS_LOCATION,
(btn, state) -> { (btn, state) -> {
((KeyBindingAccessor) this.minecraft.options.keyForward).lambdacontrols_handlePressState(state); ((KeyBindingAccessor) this.client.options.keyForward).lambdacontrols_handlePressState(state);
((KeyBindingAccessor) this.minecraft.options.keyRight).lambdacontrols_handlePressState(state); ((KeyBindingAccessor) this.client.options.keyRight).lambdacontrols_handlePressState(state);
this.updateForwardButtonsState(state); this.updateForwardButtonsState(state);
})); }));
this.forwardRightButton.visible = true; this.forwardRightButton.visible = true;
this.addButton(new SpruceTexturedButtonWidget(sneakButtonX + 20 + 5, sneakButtonY, 20, 20, 20, 80, 20, WIDGETS_LOCATION, this.addButton(new SpruceTexturedButtonWidget(sneakButtonX + 20 + 5, sneakButtonY, 20, 20, 20, 80, 20, WIDGETS_LOCATION,
(btn, state) -> ((KeyBindingAccessor) this.minecraft.options.keyRight).lambdacontrols_handlePressState(state))); (btn, state) -> ((KeyBindingAccessor) this.client.options.keyRight).lambdacontrols_handlePressState(state)));
this.addButton(new SpruceTexturedButtonWidget(sneakButtonX, sneakButtonY + 20 + 5, 20, 20, 40, 80, 20, WIDGETS_LOCATION, this.addButton(new SpruceTexturedButtonWidget(sneakButtonX, sneakButtonY + 20 + 5, 20, 20, 40, 80, 20, WIDGETS_LOCATION,
(btn, state) -> ((KeyBindingAccessor) this.minecraft.options.keyBack).lambdacontrols_handlePressState(state))); (btn, state) -> ((KeyBindingAccessor) this.client.options.keyBack).lambdacontrols_handlePressState(state)));
this.addButton(new SpruceTexturedButtonWidget(sneakButtonX - 20 - 5, sneakButtonY, 20, 20, 60, 80, 20, WIDGETS_LOCATION, this.addButton(new SpruceTexturedButtonWidget(sneakButtonX - 20 - 5, sneakButtonY, 20, 20, 60, 80, 20, WIDGETS_LOCATION,
(btn, state) -> ((KeyBindingAccessor) this.minecraft.options.keyLeft).lambdacontrols_handlePressState(state))); (btn, state) -> ((KeyBindingAccessor) this.client.options.keyLeft).lambdacontrols_handlePressState(state)));
}
@Override this.buttons.forEach(button -> {
public void render(int mouseX, int mouseY, float delta) if (button instanceof SpruceTexturedButtonWidget) {
{ ((SpruceTexturedButtonWidget) button).setSilent(true);
super.render(mouseX, mouseY, delta); }
});
} }
@Override @Override
public boolean mouseClicked(double mouseX, double mouseY, int button) public boolean mouseClicked(double mouseX, double mouseY, int button)
{ {
if (mouseY >= (double) (this.height - 22) && this.minecraft != null && this.minecraft.player != null) { if (mouseY >= (double) (this.height - 22) && this.client != null && this.client.player != null) {
int centerX = this.width / 2; int centerX = this.width / 2;
if (mouseX >= (double) (centerX - 90) && mouseX <= (double) (centerX + 90)) { if (mouseX >= (double) (centerX - 90) && mouseX <= (double) (centerX + 90)) {
for (int slot = 0; slot < 9; ++slot) { for (int slot = 0; slot < 9; ++slot) {
int slotX = centerX - 90 + slot * 20 + 2; int slotX = centerX - 90 + slot * 20 + 2;
if (mouseX >= (double) slotX && mouseX <= (double) (slotX + 20)) { if (mouseX >= (double) slotX && mouseX <= (double) (slotX + 20)) {
this.minecraft.player.inventory.selectedSlot = slot; this.client.player.inventory.selectedSlot = slot;
return true; return true;
} }
} }
@@ -281,16 +281,16 @@ public class TouchscreenOverlay extends Screen
@Override @Override
public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY)
{ {
if (button == GLFW.GLFW_MOUSE_BUTTON_1 && this.minecraft != null) { if (button == GLFW.GLFW_MOUSE_BUTTON_1 && this.client != null) {
if (deltaY > 0.01) if (deltaY > 0.01)
this.mod.input.handleLook(this.minecraft, GLFW_GAMEPAD_AXIS_RIGHT_Y, (float) Math.abs(deltaY / 5.0), 2); this.mod.input.handleLook(this.client, GLFW_GAMEPAD_AXIS_RIGHT_Y, (float) Math.abs(deltaY / 5.0), 2);
else if (deltaY < 0.01) else if (deltaY < 0.01)
this.mod.input.handleLook(this.minecraft, 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 / 5.0), 1);
if (deltaX > 0.01) if (deltaX > 0.01)
this.mod.input.handleLook(this.minecraft, GLFW_GAMEPAD_AXIS_RIGHT_X, (float) Math.abs(deltaX / 5.0), 2); this.mod.input.handleLook(this.client, GLFW_GAMEPAD_AXIS_RIGHT_X, (float) Math.abs(deltaX / 5.0), 2);
else if (deltaX < 0.01) else if (deltaX < 0.01)
this.mod.input.handleLook(this.minecraft, 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 / 5.0), 1);
} }
return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY); return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY);
} }

View File

@@ -17,5 +17,5 @@ import org.spongepowered.asm.mixin.gen.Accessor;
public interface AbstractButtonWidgetAccessor public interface AbstractButtonWidgetAccessor
{ {
@Accessor("height") @Accessor("height")
int lambdacontrols_getHeight(); int getHeight();
} }

View File

@@ -25,11 +25,11 @@ import java.util.Map;
public interface AdvancementsScreenAccessor public interface AdvancementsScreenAccessor
{ {
@Accessor("advancementHandler") @Accessor("advancementHandler")
ClientAdvancementManager lambdacontrols_getAdvancementManager(); ClientAdvancementManager getAdvancementManager();
@Accessor("tabs") @Accessor("tabs")
Map<Advancement, AdvancementTab> lambdacontrols_getTabs(); Map<Advancement, AdvancementTab> getTabs();
@Accessor("selectedTab") @Accessor("selectedTab")
AdvancementTab lambdacontrols_getSelectedTab(); AdvancementTab getSelectedTab();
} }

View File

@@ -13,7 +13,7 @@ import me.lambdaurora.lambdacontrols.LambdaControls;
import me.lambdaurora.lambdacontrols.client.LambdaControlsClient; import me.lambdaurora.lambdacontrols.client.LambdaControlsClient;
import net.fabricmc.fabric.api.network.ClientSidePacketRegistry; import net.fabricmc.fabric.api.network.ClientSidePacketRegistry;
import net.minecraft.client.network.ClientPlayNetworkHandler; import net.minecraft.client.network.ClientPlayNetworkHandler;
import net.minecraft.client.network.packet.GameJoinS2CPacket; import net.minecraft.network.packet.s2c.play.GameJoinS2CPacket;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
@@ -23,7 +23,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
public class ClientPlayNetworkHandlerMixin public class ClientPlayNetworkHandlerMixin
{ {
@Inject(method = "onGameJoin", at = @At(value = "TAIL")) @Inject(method = "onGameJoin", at = @At(value = "TAIL"))
private void lambdacontrols_onConnect(GameJoinS2CPacket packet, CallbackInfo ci) private void onGameJoin(GameJoinS2CPacket packet, CallbackInfo ci)
{ {
ClientSidePacketRegistry.INSTANCE.sendToServer(LambdaControls.HELLO_CHANNEL, LambdaControls.get().makeHello(LambdaControlsClient.get().config.getControlsMode())); ClientSidePacketRegistry.INSTANCE.sendToServer(LambdaControls.HELLO_CHANNEL, LambdaControls.get().makeHello(LambdaControlsClient.get().config.getControlsMode()));
ClientSidePacketRegistry.INSTANCE.sendToServer(LambdaControls.CONTROLS_MODE_CHANNEL, ClientSidePacketRegistry.INSTANCE.sendToServer(LambdaControls.CONTROLS_MODE_CHANNEL,

View File

@@ -52,7 +52,7 @@ public abstract class ClientPlayerEntityMixin extends AbstractClientPlayerEntity
} }
@Inject(method = "move(Lnet/minecraft/entity/MovementType;Lnet/minecraft/util/math/Vec3d;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/AbstractClientPlayerEntity;move(Lnet/minecraft/entity/MovementType;Lnet/minecraft/util/math/Vec3d;)V")) @Inject(method = "move(Lnet/minecraft/entity/MovementType;Lnet/minecraft/util/math/Vec3d;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/AbstractClientPlayerEntity;move(Lnet/minecraft/entity/MovementType;Lnet/minecraft/util/math/Vec3d;)V"))
public void lambdacontrols_move(MovementType type, Vec3d movement, CallbackInfo ci) public void onMove(MovementType type, Vec3d movement, CallbackInfo ci)
{ {
LambdaControlsClient mod = LambdaControlsClient.get(); LambdaControlsClient mod = LambdaControlsClient.get();
if (type == MovementType.SELF) { if (type == MovementType.SELF) {
@@ -70,7 +70,7 @@ public abstract class ClientPlayerEntityMixin extends AbstractClientPlayerEntity
} }
@Inject(method = "tickMovement", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;isCamera()Z")) @Inject(method = "tickMovement", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;isCamera()Z"))
public void lambdacontrols_tickMovement(CallbackInfo ci) public void onTickMovement(CallbackInfo ci)
{ {
if (this.abilities.flying && this.isCamera()) { if (this.abilities.flying && this.isCamera()) {
if (LambdaControlsClient.get().config.hasFlyVerticalDrifting()) if (LambdaControlsClient.get().config.hasFlyVerticalDrifting())

View File

@@ -1,62 +0,0 @@
/*
* Copyright © 2020 LambdAurora <aurora42lambda@gmail.com>
*
* This file is part of LambdaControls.
*
* Licensed under the MIT license. For more information,
* see the LICENSE file.
*/
package me.lambdaurora.lambdacontrols.client.mixin;
import me.lambdaurora.lambdacontrols.ControlsMode;
import me.lambdaurora.lambdacontrols.client.LambdaControlsClient;
import me.lambdaurora.lambdacontrols.client.util.ContainerScreenAccessor;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.ingame.ContainerScreen;
import net.minecraft.container.Slot;
import org.lwjgl.glfw.GLFW;
import org.spongepowered.asm.mixin.Mixin;
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;
/**
* Represents the mixin for the class ContainerScreen.
*/
@Mixin(ContainerScreen.class)
public abstract class ContainerScreenMixin implements ContainerScreenAccessor
{
protected int x;
protected int y;
@Override
public int lambdacontrols_getX()
{
return this.x;
}
@Override
public int lambdacontrols_getY()
{
return this.y;
}
@Invoker("getSlotAt")
public abstract Slot lambdacontrols_getSlotAt(double posX, double posY);
@Inject(method = "render", at = @At("RETURN"))
public void render(int mouseX, int mouseY, float delta, CallbackInfo ci)
{
if (LambdaControlsClient.get().config.getControlsMode() == ControlsMode.CONTROLLER) {
MinecraftClient client = MinecraftClient.getInstance();
int x = 10, y = client.getWindow().getScaledHeight() - 10 - 15;
x += LambdaControlsClient.drawButtonTip(x, y, new int[]{GLFW.GLFW_GAMEPAD_BUTTON_A}, "lambdacontrols.action.pickup_all", true, client) + 10;
x += LambdaControlsClient.drawButtonTip(x, y, new int[]{GLFW.GLFW_GAMEPAD_BUTTON_B}, "lambdacontrols.action.exit", true, client) + 10;
x += LambdaControlsClient.drawButtonTip(x, y, new int[]{GLFW.GLFW_GAMEPAD_BUTTON_X}, "lambdacontrols.action.pickup", true, client) + 10;
LambdaControlsClient.drawButtonTip(x, y, new int[]{GLFW.GLFW_GAMEPAD_BUTTON_Y}, "lambdacontrols.action.quick_move", true, client);
}
}
}

View File

@@ -19,6 +19,7 @@ import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.client.options.GameOptions; import net.minecraft.client.options.GameOptions;
import net.minecraft.client.resource.language.I18n; import net.minecraft.client.resource.language.I18n;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import net.minecraft.text.TranslatableText;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.Redirect;
@@ -35,12 +36,12 @@ public class ControlsOptionsScreenMixin extends GameOptionsScreen
} }
@Redirect(method = "init", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/options/ControlsOptionsScreen;addButton(Lnet/minecraft/client/gui/widget/AbstractButtonWidget;)Lnet/minecraft/client/gui/widget/AbstractButtonWidget;", ordinal = 1)) @Redirect(method = "init", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/options/ControlsOptionsScreen;addButton(Lnet/minecraft/client/gui/widget/AbstractButtonWidget;)Lnet/minecraft/client/gui/widget/AbstractButtonWidget;", ordinal = 1))
private AbstractButtonWidget on_init(ControlsOptionsScreen screen, AbstractButtonWidget btn) private AbstractButtonWidget onInit(ControlsOptionsScreen screen, AbstractButtonWidget btn)
{ {
if (this.parent instanceof ControllerControlsScreen) if (this.parent instanceof ControllerControlsScreen)
return this.addButton(btn); return this.addButton(btn);
else else
return this.addButton(new ButtonWidget(btn.x, btn.y, btn.getWidth(), ((AbstractButtonWidgetAccessor) btn).lambdacontrols_getHeight(), I18n.translate("menu.options"), return this.addButton(new ButtonWidget(btn.x, btn.y, btn.getWidth(), ((AbstractButtonWidgetAccessor) btn).getHeight(), new TranslatableText("menu.options"),
b -> this.minecraft.openScreen(new LambdaControlsSettingsScreen(this, this.gameOptions, true)))); b -> this.client.openScreen(new LambdaControlsSettingsScreen(this, true))));
} }
} }

View File

@@ -10,8 +10,8 @@
package me.lambdaurora.lambdacontrols.client.mixin; package me.lambdaurora.lambdacontrols.client.mixin;
import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen; import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen;
import net.minecraft.container.Slot;
import net.minecraft.item.ItemGroup; import net.minecraft.item.ItemGroup;
import net.minecraft.screen.slot.Slot;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
@@ -30,7 +30,7 @@ public interface CreativeInventoryScreenAccessor
* @return The selected tab index. * @return The selected tab index.
*/ */
@Accessor("selectedTab") @Accessor("selectedTab")
int lambdacontrols_getSelectedTab(); int getSelectedTab();
/** /**
* Sets the selected tab. * Sets the selected tab.
@@ -48,4 +48,12 @@ public interface CreativeInventoryScreenAccessor
*/ */
@Invoker("isCreativeInventorySlot") @Invoker("isCreativeInventorySlot")
boolean lambdacontrols_isCreativeInventorySlot(@Nullable Slot slot); boolean lambdacontrols_isCreativeInventorySlot(@Nullable Slot slot);
/**
* Returns whether the current tab has a scrollbar or not.
*
* @return True if the current tab has a scrollbar, else false.
*/
@Invoker("hasScrollbar")
boolean lambdacontrols_hasScrollbar();
} }

View File

@@ -17,5 +17,5 @@ import org.spongepowered.asm.mixin.gen.Invoker;
public interface EntryListWidgetAccessor public interface EntryListWidgetAccessor
{ {
@Invoker("moveSelection") @Invoker("moveSelection")
void lambdacontrols_moveSelection(int amount); void lambdacontrols_moveSelection(EntryListWidget.class_5403 direction);
} }

View File

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

View File

@@ -0,0 +1,72 @@
/*
* Copyright © 2020 LambdAurora <aurora42lambda@gmail.com>
*
* This file is part of LambdaControls.
*
* Licensed under the MIT license. For more information,
* see the LICENSE file.
*/
package me.lambdaurora.lambdacontrols.client.mixin;
import me.lambdaurora.lambdacontrols.ControlsMode;
import me.lambdaurora.lambdacontrols.client.LambdaControlsClient;
import me.lambdaurora.lambdacontrols.client.compat.LambdaControlsCompat;
import me.lambdaurora.lambdacontrols.client.gui.LambdaControlsRenderer;
import me.lambdaurora.lambdacontrols.client.util.HandledScreenAccessor;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.ingame.HandledScreen;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.screen.slot.Slot;
import net.minecraft.screen.slot.SlotActionType;
import org.jetbrains.annotations.Nullable;
import org.lwjgl.glfw.GLFW;
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 java.util.Arrays;
/**
* Represents the mixin for the class ContainerScreen.
*/
@Mixin(HandledScreen.class)
public abstract class HandledScreenMixin implements HandledScreenAccessor
{
@Accessor("x")
public abstract int getX();
@Accessor("y")
public abstract int getY();
@Invoker("getSlotAt")
public abstract Slot lambdacontrols_getSlotAt(double posX, double posY);
@Invoker("isClickOutsideBounds")
public abstract boolean lambdacontrols_isClickOutsideBounds(double mouseX, double mouseY, int x, int y, int button);
@Invoker("onMouseClick")
public abstract void lambdacontrols_onMouseClick(@Nullable Slot slot, int slotId, int clickData, SlotActionType actionType);
@Inject(method = "render", at = @At("RETURN"))
public void onRender(MatrixStack matrices, int mouseX, int mouseY, float delta, CallbackInfo ci)
{
if (LambdaControlsClient.get().config.getControlsMode() == ControlsMode.CONTROLLER) {
MinecraftClient client = MinecraftClient.getInstance();
int x = 2, y = client.getWindow().getScaledHeight() - 2 - LambdaControlsRenderer.ICON_SIZE;
x = LambdaControlsRenderer.drawButtonTip(matrices, x, y, new int[]{GLFW.GLFW_GAMEPAD_BUTTON_A}, "lambdacontrols.action.pickup_all", true, client) + 2;
x = LambdaControlsRenderer.drawButtonTip(matrices, x, y, new int[]{GLFW.GLFW_GAMEPAD_BUTTON_B}, "lambdacontrols.action.exit", true, client) + 2;
if (LambdaControlsCompat.isReiPresent()) {
x = 2;
y -= 24;
}
x = LambdaControlsRenderer.drawButtonTip(matrices, x, y, new int[]{GLFW.GLFW_GAMEPAD_BUTTON_X}, "lambdacontrols.action.pickup", true, client) + 2;
LambdaControlsRenderer.drawButtonTip(matrices, x, y, new int[]{GLFW.GLFW_GAMEPAD_BUTTON_Y}, "lambdacontrols.action.quick_move", true, client);
}
}
}

View File

@@ -11,16 +11,12 @@ package me.lambdaurora.lambdacontrols.client.mixin;
import me.lambdaurora.lambdacontrols.client.util.KeyBindingAccessor; import me.lambdaurora.lambdacontrols.client.util.KeyBindingAccessor;
import net.minecraft.client.options.KeyBinding; import net.minecraft.client.options.KeyBinding;
import net.minecraft.client.util.InputUtil;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
@Mixin(KeyBinding.class) @Mixin(KeyBinding.class)
public class KeyBindingMixin implements KeyBindingAccessor public class KeyBindingMixin implements KeyBindingAccessor
{ {
@Shadow
private InputUtil.KeyCode keyCode;
@Shadow @Shadow
private int timesPressed; private int timesPressed;

View File

@@ -11,13 +11,15 @@ package me.lambdaurora.lambdacontrols.client.mixin;
import me.lambdaurora.lambdacontrols.LambdaControlsFeature; import me.lambdaurora.lambdacontrols.LambdaControlsFeature;
import me.lambdaurora.lambdacontrols.client.LambdaControlsClient; import me.lambdaurora.lambdacontrols.client.LambdaControlsClient;
import net.minecraft.block.BlockState; import me.lambdaurora.lambdacontrols.client.LambdaInput;
import net.minecraft.block.FluidBlock; import me.lambdaurora.lambdacontrols.client.gui.LambdaControlsRenderer;
import me.lambdaurora.lambdacontrols.client.util.FrontBlockPlaceResultAccessor;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.client.network.ClientPlayerInteractionManager; import net.minecraft.client.network.ClientPlayerInteractionManager;
import net.minecraft.client.render.GameRenderer; import net.minecraft.client.render.GameRenderer;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.client.world.ClientWorld; import net.minecraft.client.world.ClientWorld;
import net.minecraft.item.BlockItem; import net.minecraft.item.BlockItem;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
@@ -27,7 +29,7 @@ import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.hit.HitResult; import net.minecraft.util.hit.HitResult;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction; import net.minecraft.util.math.Direction;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
@@ -38,7 +40,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
@Mixin(MinecraftClient.class) @Mixin(MinecraftClient.class)
public abstract class MinecraftClientMixin public abstract class MinecraftClientMixin implements FrontBlockPlaceResultAccessor
{ {
@Shadow @Shadow
@Nullable @Nullable
@@ -60,43 +62,97 @@ public abstract class MinecraftClientMixin
@Final @Final
public GameRenderer gameRenderer; public GameRenderer gameRenderer;
@Shadow
private int itemUseCooldown;
private BlockHitResult lambdacontrols_frontBlockPlaceResult = null;
private BlockPos lambdacontrols_lastTargetPos;
private Vec3d lambdacontrols_lastPos;
private Direction lambdacontrols_lastTargetSide;
@Override
public @Nullable BlockHitResult lambdacontrols_getFrontBlockPlaceResult()
{
return this.lambdacontrols_frontBlockPlaceResult;
}
@Inject(method = "<init>", at = @At("RETURN")) @Inject(method = "<init>", at = @At("RETURN"))
private void lambdacontrols_onInit(CallbackInfo ci) private void onInit(CallbackInfo ci)
{ {
LambdaControlsClient.get().onMcInit((MinecraftClient) (Object) this); LambdaControlsClient.get().onMcInit((MinecraftClient) (Object) this);
} }
@Inject(method = "tick", at = @At("HEAD"))
private void onStartTick(CallbackInfo ci)
{
if (this.player == null)
return;
this.lambdacontrols_frontBlockPlaceResult = LambdaInput.tryFrontPlace(((MinecraftClient) (Object) this));
if (!LambdaControlsFeature.FAST_BLOCK_PLACING.isAvailable())
return;
if (this.lambdacontrols_lastPos == null)
this.lambdacontrols_lastPos = this.player.getPos();
int cooldown = this.itemUseCooldown;
BlockHitResult hitResult;
if (this.crosshairTarget != null && this.crosshairTarget.getType() == HitResult.Type.BLOCK && this.player.abilities.flying) {
hitResult = (BlockHitResult) this.crosshairTarget;
BlockPos targetPos = hitResult.getBlockPos();
Direction side = hitResult.getSide();
boolean sidewaysBlockPlacing = this.lambdacontrols_lastTargetPos == null || !targetPos.equals(this.lambdacontrols_lastTargetPos.offset(this.lambdacontrols_lastTargetSide));
boolean backwardsBlockPlacing = this.player.input.movementForward < 0.0f && (this.lambdacontrols_lastTargetPos == null || targetPos.equals(this.lambdacontrols_lastTargetPos.offset(this.lambdacontrols_lastTargetSide)));
if (cooldown > 1
&& !targetPos.equals(this.lambdacontrols_lastTargetPos)
&& (sidewaysBlockPlacing || backwardsBlockPlacing)) {
this.itemUseCooldown = 1;
}
this.lambdacontrols_lastTargetPos = targetPos.toImmutable();
this.lambdacontrols_lastTargetSide = side;
}
// Removed front placing sprinting as way too cheaty.
/* else if (this.player.isSprinting()) {
hitResult = this.lambdacontrols_frontBlockPlaceResult;
if (hitResult != null) {
if (cooldown > 0)
this.itemUseCooldown = 0;
}
} */
this.lambdacontrols_lastPos = this.player.getPos();
}
@Inject(method = "render", at = @At("HEAD")) @Inject(method = "render", at = @At("HEAD"))
private void lambdacontrols_onRender(boolean fullRender, CallbackInfo ci) private void onRender(boolean fullRender, CallbackInfo ci)
{ {
LambdaControlsClient.get().onRender((MinecraftClient) (Object) (this)); LambdaControlsClient.get().onRender((MinecraftClient) (Object) (this));
} }
@Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/GameRenderer;render(FJZ)V", shift = At.Shift.AFTER))
private void renderVirtualCursor(boolean fullRender, CallbackInfo ci) {
LambdaControlsRenderer.renderVirtualCursor(new MatrixStack(), (MinecraftClient) (Object) this);
}
@Inject(method = "disconnect(Lnet/minecraft/client/gui/screen/Screen;)V", at = @At("RETURN")) @Inject(method = "disconnect(Lnet/minecraft/client/gui/screen/Screen;)V", at = @At("RETURN"))
private void lambdacontrols_onLeave(@Nullable Screen screen, CallbackInfo ci) private void onLeave(@Nullable Screen screen, CallbackInfo ci)
{ {
LambdaControlsClient.get().onLeave(); LambdaControlsClient.get().onLeave();
} }
@Inject(method = "doItemUse()V", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/hit/HitResult;getType()Lnet/minecraft/util/hit/HitResult$Type;"), locals = LocalCapture.CAPTURE_FAILEXCEPTION, cancellable = true) @Inject(method = "doItemUse()V", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/hit/HitResult;getType()Lnet/minecraft/util/hit/HitResult$Type;"), locals = LocalCapture.CAPTURE_FAILEXCEPTION, cancellable = true)
private void lambdacontrols_onItemUse(CallbackInfo ci, Hand[] hands, int handCount, int handIndex, Hand hand, ItemStack stackInHand) private void onItemUse(CallbackInfo ci, Hand[] hands, int handCount, int handIndex, Hand hand, ItemStack stackInHand)
{ {
if (!stackInHand.isEmpty() && this.player.pitch > 35.0F && LambdaControlsFeature.FRONT_BLOCK_PLACING.isAvailable()) { if (!stackInHand.isEmpty() && this.player.pitch > 35.0F && LambdaControlsFeature.FRONT_BLOCK_PLACING.isAvailable()) {
if (this.crosshairTarget != null && this.crosshairTarget.getType() == HitResult.Type.MISS && this.player.onGround) { if (this.crosshairTarget != null && this.crosshairTarget.getType() == HitResult.Type.MISS && this.player.isOnGround()) {
if (!stackInHand.isEmpty() && stackInHand.getItem() instanceof BlockItem) { if (!stackInHand.isEmpty() && stackInHand.getItem() instanceof BlockItem) {
BlockPos playerPos = this.player.getBlockPos().down(); BlockHitResult hitResult = LambdaInput.tryFrontPlace(((MinecraftClient) (Object) this));
BlockPos targetPos = new BlockPos(this.crosshairTarget.getPos()).subtract(playerPos);
BlockPos vector = new BlockPos(MathHelper.clamp(targetPos.getX(), -1, 1), 0, MathHelper.clamp(targetPos.getZ(), -1, 1));
BlockPos blockPos = playerPos.add(vector);
Direction direction = player.getHorizontalFacing(); if (hitResult == null)
BlockState adjacentBlockState = this.world.getBlockState(blockPos.offset(direction.getOpposite()));
if (adjacentBlockState.isAir() || adjacentBlockState.getBlock() instanceof FluidBlock || (vector.getX() == 0 && vector.getZ() == 0)) {
return; return;
}
BlockHitResult hitResult = new BlockHitResult(this.crosshairTarget.getPos(), direction.getOpposite(), blockPos, false); hitResult = LambdaInput.withSideForFrontPlace(hitResult, stackInHand);
int previousStackCount = stackInHand.getCount(); int previousStackCount = stackInHand.getCount();
ActionResult result = this.interactionManager.interactBlock(this.player, this.world, hand, hitResult); ActionResult result = this.interactionManager.interactBlock(this.player, this.world, hand, hitResult);

View File

@@ -11,13 +11,18 @@ package me.lambdaurora.lambdacontrols.client.mixin;
import me.lambdaurora.lambdacontrols.ControlsMode; import me.lambdaurora.lambdacontrols.ControlsMode;
import me.lambdaurora.lambdacontrols.client.LambdaControlsClient; import me.lambdaurora.lambdacontrols.client.LambdaControlsClient;
import me.lambdaurora.lambdacontrols.client.LambdaControlsConfig;
import me.lambdaurora.lambdacontrols.client.util.MouseAccessor; import me.lambdaurora.lambdacontrols.client.util.MouseAccessor;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.Mouse; import net.minecraft.client.Mouse;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.gen.Invoker;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
/** /**
* Adds extra access to the mouse. * Adds extra access to the mouse.
@@ -26,21 +31,30 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
public abstract class MouseMixin implements MouseAccessor public abstract class MouseMixin implements MouseAccessor
{ {
@Shadow @Shadow
protected abstract void onCursorPos(long window, double x, double y); @Final
private MinecraftClient client;
@Shadow @Invoker("onCursorPos")
protected abstract void onMouseButton(long window, int button, int action, int mods); public abstract void lambdacontrols_onCursorPos(long window, double x, double y);
@Inject(method = "isCursorLocked", at = @At("HEAD"), cancellable = true)
private void isCursorLocked(CallbackInfoReturnable<Boolean> ci)
{
if (client.currentScreen == null) {
LambdaControlsConfig config = LambdaControlsClient.get().config;
if (config.getControlsMode() == ControlsMode.CONTROLLER && config.hasVirtualMouse()) {
ci.setReturnValue(true);
ci.cancel();
}
}
}
@Inject(method = "lockCursor", at = @At("HEAD"), cancellable = true) @Inject(method = "lockCursor", at = @At("HEAD"), cancellable = true)
private void lambdacontrols_onMouseLocked(CallbackInfo ci) private void onCursorLocked(CallbackInfo ci)
{ {
if (LambdaControlsClient.get().config.getControlsMode() == ControlsMode.TOUCHSCREEN) LambdaControlsConfig config = LambdaControlsClient.get().config;
if (config.getControlsMode() == ControlsMode.TOUCHSCREEN
|| (config.getControlsMode() == ControlsMode.CONTROLLER && config.hasVirtualMouse()))
ci.cancel(); ci.cancel();
} }
@Override
public void lambdacontrols_onCursorPos(long window, double x, double y)
{
this.onCursorPos(window, x, y);
}
} }

View File

@@ -13,7 +13,7 @@ import me.lambdaurora.lambdacontrols.ControlsMode;
import me.lambdaurora.lambdacontrols.client.LambdaControlsClient; import me.lambdaurora.lambdacontrols.client.LambdaControlsClient;
import me.lambdaurora.lambdacontrols.client.gui.ControllerControlsScreen; import me.lambdaurora.lambdacontrols.client.gui.ControllerControlsScreen;
import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.screen.SettingsScreen; import net.minecraft.client.gui.screen.options.OptionsScreen;
import net.minecraft.client.gui.widget.AbstractButtonWidget; import net.minecraft.client.gui.widget.AbstractButtonWidget;
import net.minecraft.client.gui.widget.ButtonWidget; import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.text.Text; import net.minecraft.text.Text;
@@ -24,20 +24,20 @@ import org.spongepowered.asm.mixin.injection.Redirect;
/** /**
* Injects the new controls settings button. * Injects the new controls settings button.
*/ */
@Mixin(SettingsScreen.class) @Mixin(OptionsScreen.class)
public class SettingsScreenMixin extends Screen public class OptionsScreenMixin extends Screen
{ {
protected SettingsScreenMixin(Text title) protected OptionsScreenMixin(Text title)
{ {
super(title); super(title);
} }
@Redirect(method = "init", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/SettingsScreen;addButton(Lnet/minecraft/client/gui/widget/AbstractButtonWidget;)Lnet/minecraft/client/gui/widget/AbstractButtonWidget;", ordinal = 7)) @Redirect(method = "init", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/options/OptionsScreen;addButton(Lnet/minecraft/client/gui/widget/AbstractButtonWidget;)Lnet/minecraft/client/gui/widget/AbstractButtonWidget;", ordinal = 7))
private AbstractButtonWidget lambdacontrols_onInit(SettingsScreen screen, AbstractButtonWidget btn) private AbstractButtonWidget lambdacontrols_onInit(OptionsScreen screen, AbstractButtonWidget btn)
{ {
if (LambdaControlsClient.get().config.getControlsMode() == ControlsMode.CONTROLLER) { if (LambdaControlsClient.get().config.getControlsMode() == ControlsMode.CONTROLLER) {
return this.addButton(new ButtonWidget(btn.x, btn.y, btn.getWidth(), ((AbstractButtonWidgetAccessor) btn).lambdacontrols_getHeight(), btn.getMessage(), return this.addButton(new ButtonWidget(btn.x, btn.y, btn.getWidth(), ((AbstractButtonWidgetAccessor) btn).getHeight(), btn.getMessage(),
b -> this.minecraft.openScreen(new ControllerControlsScreen(this, false)))); b -> this.client.openScreen(new ControllerControlsScreen(this, false))));
} else { } else {
return this.addButton(btn); return this.addButton(btn);
} }

View File

@@ -0,0 +1,34 @@
/*
* Copyright © 2020 LambdAurora <aurora42lambda@gmail.com>
*
* This file is part of LambdaControls.
*
* Licensed under the MIT license. For more information,
* see the LICENSE file.
*/
package me.lambdaurora.lambdacontrols.client.mixin;
import net.minecraft.client.gui.screen.recipebook.RecipeBookWidget;
import net.minecraft.client.gui.screen.recipebook.RecipeGroupButtonWidget;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import org.spongepowered.asm.mixin.gen.Invoker;
import java.util.List;
@Mixin(RecipeBookWidget.class)
public interface RecipeBookWidgetAccessor
{
@Accessor("tabButtons")
List<RecipeGroupButtonWidget> getTabButtons();
@Accessor("currentTab")
RecipeGroupButtonWidget getCurrentTab();
@Accessor("currentTab")
void setCurrentTab(RecipeGroupButtonWidget currentTab);
@Invoker("refreshResults")
void lambdacontrols_refreshResults(boolean resetCurrentPage);
}

View File

@@ -0,0 +1,99 @@
/*
* Copyright © 2020 LambdAurora <aurora42lambda@gmail.com>
*
* This file is part of LambdaControls.
*
* Licensed under the MIT license. For more information,
* see the LICENSE file.
*/
package me.lambdaurora.lambdacontrols.client.mixin;
import me.lambdaurora.lambdacontrols.client.LambdaControlsClient;
import me.lambdaurora.lambdacontrols.client.LambdaInput;
import me.lambdaurora.lambdacontrols.client.util.FrontBlockPlaceResultAccessor;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.ShapeContext;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.*;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.item.BlockItem;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemUsageContext;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.hit.HitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Matrix4f;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.profiler.Profiler;
import net.minecraft.util.shape.VoxelShape;
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;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
/**
* Represents a mixin to WorldRenderer.
* <p>
* Handles the rendering of the block outline of the front block placing.
*/
@Mixin(WorldRenderer.class)
public abstract class WorldRendererMixin
{
@Shadow
@Final
private MinecraftClient client;
@Shadow
private ClientWorld world;
@Shadow
private static void drawShapeOutline(MatrixStack matrixStack, VertexConsumer vertexConsumer, VoxelShape voxelShape, double d, double e, double f, float g, float h, float i, float j)
{
}
@Inject(
method = "render",
at = @At(
value = "FIELD",
target = "Lnet/minecraft/client/MinecraftClient;crosshairTarget:Lnet/minecraft/util/hit/HitResult;",
ordinal = 1,
shift = At.Shift.AFTER
),
locals = LocalCapture.CAPTURE_FAILEXCEPTION
)
private void onOutlineRender(MatrixStack matrices, float tickDelta, long limitTime, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer,
LightmapTextureManager lightmapTextureManager, Matrix4f matrix4f, CallbackInfo ci,
Profiler profiler, Vec3d cameraPos, double x, double y, double z, Matrix4f modelMatrix, boolean bl, Frustum frustum2, boolean bl3,
VertexConsumerProvider.Immediate immediate)
{
if (this.client.crosshairTarget == null || this.client.crosshairTarget.getType() != HitResult.Type.MISS || !LambdaControlsClient.get().config.shouldRenderFrontBlockOutline())
return;
BlockHitResult result = ((FrontBlockPlaceResultAccessor) client).lambdacontrols_getFrontBlockPlaceResult();
if (result == null)
return;
BlockPos blockPos = result.getBlockPos();
if (this.world.getWorldBorder().contains(blockPos)) {
ItemStack stack = this.client.player.getStackInHand(Hand.MAIN_HAND);
if (stack == null || !(stack.getItem() instanceof BlockItem))
return;
Block block = ((BlockItem) stack.getItem()).getBlock();
result = LambdaInput.withSideForFrontPlace(result, block);
ItemPlacementContext context = new ItemPlacementContext(new ItemUsageContext(this.client.player, Hand.MAIN_HAND, result));
VertexConsumer vertexConsumer = immediate.getBuffer(RenderLayer.getLines());
BlockState placementState = block.getPlacementState(context);
if (placementState == null)
return;
VoxelShape outlineShape = placementState.getOutlineShape(this.client.world, blockPos, ShapeContext.of(camera.getFocusedEntity()));
int[] color = LambdaControlsClient.get().config.getFrontBlockOutlineColor();
drawShapeOutline(matrices, vertexConsumer, outlineShape, (double) blockPos.getX() - x, (double) blockPos.getY() - y, (double) blockPos.getZ() - z, color[0] / 255.f, color[1] / 255.f, color[2] / 255.f, color[3] / 255.f);
}
}
}

View File

@@ -0,0 +1,22 @@
/*
* Copyright © 2020 LambdAurora <aurora42lambda@gmail.com>
*
* This file is part of LambdaControls.
*
* Licensed under the MIT license. For more information,
* see the LICENSE file.
*/
package me.lambdaurora.lambdacontrols.client.ring;
/**
* Represents a key binding ring.
*
* @author LambdAurora
* @version 1.4.0
* @since 1.4.0
*/
public class KeyBindingRing
{
}

View File

@@ -0,0 +1,32 @@
/*
* Copyright © 2020 LambdAurora <aurora42lambda@gmail.com>
*
* This file is part of LambdaControls.
*
* Licensed under the MIT license. For more information,
* see the LICENSE file.
*/
package me.lambdaurora.lambdacontrols.client.util;
import net.minecraft.util.hit.BlockHitResult;
import org.jetbrains.annotations.Nullable;
/**
* Represents an accessor of the BlockHitResult for the front block placing feature.
* <p>
* It is implemented by {@link net.minecraft.client.MinecraftClient}.
*
* @author LambdAurora
* @version 1.2.0
* @since 1.2.0
*/
public interface FrontBlockPlaceResultAccessor
{
/**
* Returns the {@link BlockHitResult} if a block can be placed with the front block placing feature.
*
* @return If possible a {@link BlockHitResult}, else a null value.
*/
@Nullable BlockHitResult lambdacontrols_getFrontBlockPlaceResult();
}

View File

@@ -9,26 +9,28 @@
package me.lambdaurora.lambdacontrols.client.util; package me.lambdaurora.lambdacontrols.client.util;
import net.minecraft.container.Slot; import net.minecraft.screen.slot.Slot;
import net.minecraft.screen.slot.SlotActionType;
import org.jetbrains.annotations.Nullable;
/** /**
* Represents an accessor to AbstractContainerScreen. * Represents an accessor to AbstractContainerScreen.
*/ */
public interface ContainerScreenAccessor public interface HandledScreenAccessor
{ {
/** /**
* Gets the left coordinate of the GUI. * Gets the left coordinate of the GUI.
* *
* @return The left coordinate of the GUI. * @return The left coordinate of the GUI.
*/ */
int lambdacontrols_getX(); int getX();
/** /**
* Gets the top coordinate of the GUI. * Gets the top coordinate of the GUI.
* *
* @return The top coordinate of the GUI. * @return The top coordinate of the GUI.
*/ */
int lambdacontrols_getY(); int getY();
/** /**
* Gets the slot at position. * Gets the slot at position.
@@ -38,4 +40,16 @@ public interface ContainerScreenAccessor
* @return The slot at the specified position. * @return The slot at the specified position.
*/ */
Slot lambdacontrols_getSlotAt(double pos_x, double pos_y); Slot lambdacontrols_getSlotAt(double pos_x, double pos_y);
boolean lambdacontrols_isClickOutsideBounds(double mouseX, double mouseY, int x, int y, int button);
/**
* Handles a mouse click on the specified slot.
*
* @param slot The slot instance.
* @param slotId The slot id.
* @param clickData The click data.
* @param actionType The action type.
*/
void lambdacontrols_onMouseClick(@Nullable Slot slot, int slotId, int clickData, SlotActionType actionType);
} }

View File

@@ -19,6 +19,7 @@
"lambdacontrols.action.pick_block": "Pick Block", "lambdacontrols.action.pick_block": "Pick Block",
"lambdacontrols.action.pickup": "Pickup", "lambdacontrols.action.pickup": "Pickup",
"lambdacontrols.action.pickup_all": "Pickup all", "lambdacontrols.action.pickup_all": "Pickup all",
"lambdacontrols.action.place": "Place",
"lambdacontrols.action.player_list": "Player List", "lambdacontrols.action.player_list": "Player List",
"lambdacontrols.action.quick_move": "Quick move", "lambdacontrols.action.quick_move": "Quick move",
"lambdacontrols.action.right": "Right", "lambdacontrols.action.right": "Right",
@@ -59,7 +60,6 @@
"lambdacontrols.controller.connected": "Controller %d connected.", "lambdacontrols.controller.connected": "Controller %d connected.",
"lambdacontrols.controller.disconnected": "Controller %d disconnected.", "lambdacontrols.controller.disconnected": "Controller %d disconnected.",
"lambdacontrols.controller.mappings.1": "To configure the controller mappings, please use %sSDL2 Gamepad Tool%s", "lambdacontrols.controller.mappings.1": "To configure the controller mappings, please use %sSDL2 Gamepad Tool%s",
"lambdacontrols.controller.mappings.2": "(%s%s%s),",
"lambdacontrols.controller.mappings.3": "and put the mapping in `%s.minecraft/config/gamecontrollerdb.txt%s`.", "lambdacontrols.controller.mappings.3": "and put the mapping in `%s.minecraft/config/gamecontrollerdb.txt%s`.",
"lambdacontrols.controller.mappings.updated": "Updated mappings!", "lambdacontrols.controller.mappings.updated": "Updated mappings!",
"lambdacontrols.controller_type.default": "default", "lambdacontrols.controller_type.default": "default",
@@ -79,6 +79,7 @@
"lambdacontrols.menu.controller_type": "Controller Type", "lambdacontrols.menu.controller_type": "Controller Type",
"lambdacontrols.menu.controls_mode": "Mode", "lambdacontrols.menu.controls_mode": "Mode",
"lambdacontrols.menu.dead_zone": "Dead Zone", "lambdacontrols.menu.dead_zone": "Dead Zone",
"lambdacontrols.menu.fast_block_placing": "Fast Block Placing",
"lambdacontrols.menu.fly_drifting": "Fly Drifting", "lambdacontrols.menu.fly_drifting": "Fly Drifting",
"lambdacontrols.menu.fly_drifting_vertical": "Vertical Fly Drifting", "lambdacontrols.menu.fly_drifting_vertical": "Vertical Fly Drifting",
"lambdacontrols.menu.front_block_placing": "Front Block Placing", "lambdacontrols.menu.front_block_placing": "Front Block Placing",
@@ -98,6 +99,8 @@
"lambdacontrols.menu.title.hud": "HUD Options", "lambdacontrols.menu.title.hud": "HUD Options",
"lambdacontrols.menu.unbound": "Unbound", "lambdacontrols.menu.unbound": "Unbound",
"lambdacontrols.menu.unfocused_input": "Unfocused Input", "lambdacontrols.menu.unfocused_input": "Unfocused Input",
"lambdacontrols.menu.virtual_mouse": "Virtual Mouse",
"lambdacontrols.menu.virtual_mouse.skin": "Virtual Mouse Skin",
"lambdacontrols.narrator.unbound": "Unbound %s", "lambdacontrols.narrator.unbound": "Unbound %s",
"lambdacontrols.not_bound": "Not bound", "lambdacontrols.not_bound": "Not bound",
"lambdacontrols.tooltip.auto_switch_mode": "If the controls mode should be switched to Controller automatically if one is connected.", "lambdacontrols.tooltip.auto_switch_mode": "If the controls mode should be switched to Controller automatically if one is connected.",
@@ -105,13 +108,19 @@
"lambdacontrols.tooltip.controller_type": "The controller type to display the correct buttons.", "lambdacontrols.tooltip.controller_type": "The controller type to display the correct buttons.",
"lambdacontrols.tooltip.controls_mode": "The controls mode.", "lambdacontrols.tooltip.controls_mode": "The controls mode.",
"lambdacontrols.tooltip.dead_zone": "The dead zone for the controller's analogue sticks.", "lambdacontrols.tooltip.dead_zone": "The dead zone for the controller's analogue sticks.",
"lambdacontrols.tooltip.fly_drifting": "While flying, enables drifting/inertia.", "lambdacontrols.tooltip.fast_block_placing": "While flying in creative mode, enables fast block placing depending on your speed. §cOn some servers this might be considered as cheating.",
"lambdacontrols.tooltip.fly_drifting_vertical": "While flying, enables vertical drifting/intertia.", "lambdacontrols.tooltip.fly_drifting": "While flying, enables Vanilla drifting/inertia.",
"lambdacontrols.tooltip.fly_drifting_vertical": "While flying, enables Vanilla vertical drifting/intertia.",
"lambdacontrols.tooltip.front_block_placing": "Enables front block placing, §cmight be considered cheating on some servers§r.", "lambdacontrols.tooltip.front_block_placing": "Enables front block placing, §cmight be considered cheating on some servers§r.",
"lambdacontrols.tooltip.hud_enable": "Toggles the on-screen controller button indicator.", "lambdacontrols.tooltip.hud_enable": "Toggles the on-screen controller button indicator.",
"lambdacontrols.tooltip.hud_side": "The position of the HUD.", "lambdacontrols.tooltip.hud_side": "The position of the HUD.",
"lambdacontrols.tooltip.mouse_speed": "The controller's emulated mouse speed.", "lambdacontrols.tooltip.mouse_speed": "The controller's emulated mouse speed.",
"lambdacontrols.tooltip.rotation_speed": "The camera rotation speed in controller mode.", "lambdacontrols.tooltip.rotation_speed": "The camera rotation speed in controller mode.",
"lambdacontrols.tooltip.reload_controller_mappings": "Reloads the controller mappings file.", "lambdacontrols.tooltip.reload_controller_mappings": "Reloads the controller mappings file.",
"lambdacontrols.tooltip.unfocused_input": "Allow controller input when the window is not focused." "lambdacontrols.tooltip.unfocused_input": "Allow controller input when the window is not focused.",
"lambdacontrols.tooltip.virtual_mouse": "Enable the virtual mouse which is handful in the case of a splitscreen.",
"lambdacontrols.virtual_mouse.skin.default_light": "Default Light",
"lambdacontrols.virtual_mouse.skin.default_dark": "Default Dark",
"lambdacontrols.virtual_mouse.skin.second_light": "Second Light",
"lambdacontrols.virtual_mouse.skin.second_dark": "Second Dark"
} }

View File

@@ -19,6 +19,7 @@
"lambdacontrols.action.pick_block": "Choisir le bloc", "lambdacontrols.action.pick_block": "Choisir le bloc",
"lambdacontrols.action.pickup": "Prendre", "lambdacontrols.action.pickup": "Prendre",
"lambdacontrols.action.pickup_all": "Prendre tout", "lambdacontrols.action.pickup_all": "Prendre tout",
"lambdacontrols.action.place": "Placer",
"lambdacontrols.action.player_list": "Afficher la liste des joueurs", "lambdacontrols.action.player_list": "Afficher la liste des joueurs",
"lambdacontrols.action.quick_move": "Mouvement rapide", "lambdacontrols.action.quick_move": "Mouvement rapide",
"lambdacontrols.action.right": "Aller à droite", "lambdacontrols.action.right": "Aller à droite",
@@ -59,7 +60,6 @@
"lambdacontrols.controller.connected": "Manette %d connecté.", "lambdacontrols.controller.connected": "Manette %d connecté.",
"lambdacontrols.controller.disconnected": "Manette %d déconnecté.", "lambdacontrols.controller.disconnected": "Manette %d déconnecté.",
"lambdacontrols.controller.mappings.1": "Pour configurer les correspondances de la manette, veuillez utiliser %sSDL2 Gamepad Tool%s", "lambdacontrols.controller.mappings.1": "Pour configurer les correspondances de la manette, veuillez utiliser %sSDL2 Gamepad Tool%s",
"lambdacontrols.controller.mappings.2": "(%s%s%s),",
"lambdacontrols.controller.mappings.3": "et mettez les correspondances dans le fichier `%s.minecraft/config/gamecontrollerdb.txt%s`.", "lambdacontrols.controller.mappings.3": "et mettez les correspondances dans le fichier `%s.minecraft/config/gamecontrollerdb.txt%s`.",
"lambdacontrols.controller.mappings.updated": "Configuration des manettes mise à jour!", "lambdacontrols.controller.mappings.updated": "Configuration des manettes mise à jour!",
"lambdacontrols.controller_type.default": "default", "lambdacontrols.controller_type.default": "default",
@@ -98,6 +98,8 @@
"lambdacontrols.menu.title.hud": "Options du HUD", "lambdacontrols.menu.title.hud": "Options du HUD",
"lambdacontrols.menu.unbound": "Délier", "lambdacontrols.menu.unbound": "Délier",
"lambdacontrols.menu.unfocused_input": "Entrée en fond", "lambdacontrols.menu.unfocused_input": "Entrée en fond",
"lambdacontrols.menu.virtual_mouse": "Souris virtuelle",
"lambdacontrols.menu.virtual_mouse.skin": "Apparence souris virtuelle",
"lambdacontrols.narrator.unbound": "Délier %s", "lambdacontrols.narrator.unbound": "Délier %s",
"lambdacontrols.not_bound": "Non défini", "lambdacontrols.not_bound": "Non défini",
"lambdacontrols.tooltip.auto_switch_mode": "Détermine si le mode de contrôle doit automatiquement changer sur Manette si une manette est connectée et inversement.", "lambdacontrols.tooltip.auto_switch_mode": "Détermine si le mode de contrôle doit automatiquement changer sur Manette si une manette est connectée et inversement.",
@@ -105,13 +107,18 @@
"lambdacontrols.tooltip.controller_type": "Le type de contrôle n'influe que sur les boutons affichés.", "lambdacontrols.tooltip.controller_type": "Le type de contrôle n'influe que sur les boutons affichés.",
"lambdacontrols.tooltip.controls_mode": "Change le mode de contrôle.", "lambdacontrols.tooltip.controls_mode": "Change le mode de contrôle.",
"lambdacontrols.tooltip.dead_zone": "Zone morte des axes de la manette.", "lambdacontrols.tooltip.dead_zone": "Zone morte des axes de la manette.",
"lambdacontrols.tooltip.fly_drifting": "Pendant que le joueur vole, active le glissement.", "lambdacontrols.tooltip.fly_drifting": "Pendant que le joueur vole, active le glissement Vanilla.",
"lambdacontrols.tooltip.fly_drifting_vertical": "Pendant que le joueur vole, active le glissement vertical.", "lambdacontrols.tooltip.fly_drifting_vertical": "Pendant que le joueur vole, active le glissement vertical Vanilla.",
"lambdacontrols.tooltip.front_block_placing": "Active le placement avant de blocs, §cpeut être considérer comme de la trice sur certains serveurs§r.", "lambdacontrols.tooltip.front_block_placing": "Active le placement avant de blocs, §cpeut être considérer comme de la trice sur certains serveurs§r.",
"lambdacontrols.tooltip.hud_enable": "Détermine si l'indicateur des buttons de la manette doit être affiché ou non.", "lambdacontrols.tooltip.hud_enable": "Détermine si l'indicateur des buttons de la manette doit être affiché ou non.",
"lambdacontrols.tooltip.hud_side": "Change la position du HUD.", "lambdacontrols.tooltip.hud_side": "Change la position du HUD.",
"lambdacontrols.tooltip.mouse_speed": "Change la vitesse de la souris émulée par la manette.", "lambdacontrols.tooltip.mouse_speed": "Change la vitesse de la souris émulée par la manette.",
"lambdacontrols.tooltip.rotation_speed": "Change la vitesse de rotation de la caméra.", "lambdacontrols.tooltip.rotation_speed": "Change la vitesse de rotation de la caméra.",
"lambdacontrols.tooltip.reload_controller_mappings": "Recharge le fichier de configuration des manettes.", "lambdacontrols.tooltip.reload_controller_mappings": "Recharge le fichier de configuration des manettes.",
"lambdacontrols.tooltip.unfocused_input": "Autorise les entrées manette quand la fenêtre n'est pas sélectionnée." "lambdacontrols.tooltip.unfocused_input": "Autorise les entrées manette quand la fenêtre n'est pas sélectionnée.",
"lambdacontrols.tooltip.virtual_mouse": "Active la souris virtuelle qui est pratique dans le cas d'un écran partagé.",
"lambdacontrols.virtual_mouse.skin.default_light": "défaut clair",
"lambdacontrols.virtual_mouse.skin.default_dark": "défaut foncé",
"lambdacontrols.virtual_mouse.skin.second_light": "second clair",
"lambdacontrols.virtual_mouse.skin.second_dark": "second foncé"
} }

View File

@@ -19,6 +19,7 @@
"lambdacontrols.action.pick_block": "Choisir le bloc", "lambdacontrols.action.pick_block": "Choisir le bloc",
"lambdacontrols.action.pickup": "Prendre", "lambdacontrols.action.pickup": "Prendre",
"lambdacontrols.action.pickup_all": "Prendre tout", "lambdacontrols.action.pickup_all": "Prendre tout",
"lambdacontrols.action.place": "Placer",
"lambdacontrols.action.player_list": "Afficher la liste des joueurs", "lambdacontrols.action.player_list": "Afficher la liste des joueurs",
"lambdacontrols.action.quick_move": "Mouvement rapide", "lambdacontrols.action.quick_move": "Mouvement rapide",
"lambdacontrols.action.right": "Aller à droite", "lambdacontrols.action.right": "Aller à droite",
@@ -59,7 +60,6 @@
"lambdacontrols.controller.connected": "Manette %d connecté.", "lambdacontrols.controller.connected": "Manette %d connecté.",
"lambdacontrols.controller.disconnected": "Manette %d déconnecté.", "lambdacontrols.controller.disconnected": "Manette %d déconnecté.",
"lambdacontrols.controller.mappings.1": "Pour configurer les correspondances de la manette, veuillez utiliser %sSDL2 Gamepad Tool%s", "lambdacontrols.controller.mappings.1": "Pour configurer les correspondances de la manette, veuillez utiliser %sSDL2 Gamepad Tool%s",
"lambdacontrols.controller.mappings.2": "(%s%s%s),",
"lambdacontrols.controller.mappings.3": "et mettez les correspondances dans le fichier `%s.minecraft/config/gamecontrollerdb.txt%s`.", "lambdacontrols.controller.mappings.3": "et mettez les correspondances dans le fichier `%s.minecraft/config/gamecontrollerdb.txt%s`.",
"lambdacontrols.controller.mappings.updated": "Configuration des manettes mise à jour!", "lambdacontrols.controller.mappings.updated": "Configuration des manettes mise à jour!",
"lambdacontrols.controller_type.default": "default", "lambdacontrols.controller_type.default": "default",
@@ -98,6 +98,8 @@
"lambdacontrols.menu.title.hud": "Options du HUD", "lambdacontrols.menu.title.hud": "Options du HUD",
"lambdacontrols.menu.unbound": "Délier", "lambdacontrols.menu.unbound": "Délier",
"lambdacontrols.menu.unfocused_input": "Entrée en fond", "lambdacontrols.menu.unfocused_input": "Entrée en fond",
"lambdacontrols.menu.virtual_mouse": "Souris virtuelle",
"lambdacontrols.menu.virtual_mouse.skin": "Apparence souris virtuelle",
"lambdacontrols.narrator.unbound": "Délier %s", "lambdacontrols.narrator.unbound": "Délier %s",
"lambdacontrols.not_bound": "Non défini", "lambdacontrols.not_bound": "Non défini",
"lambdacontrols.tooltip.auto_switch_mode": "Détermine si le mode de contrôle doit automatiquement changer sur Manette si une manette est connectée et inversement.", "lambdacontrols.tooltip.auto_switch_mode": "Détermine si le mode de contrôle doit automatiquement changer sur Manette si une manette est connectée et inversement.",
@@ -105,13 +107,18 @@
"lambdacontrols.tooltip.controller_type": "Le type de contrôle n'influe que sur les boutons affichés.", "lambdacontrols.tooltip.controller_type": "Le type de contrôle n'influe que sur les boutons affichés.",
"lambdacontrols.tooltip.controls_mode": "Change le mode de contrôle.", "lambdacontrols.tooltip.controls_mode": "Change le mode de contrôle.",
"lambdacontrols.tooltip.dead_zone": "Zone morte des axes de la manette.", "lambdacontrols.tooltip.dead_zone": "Zone morte des axes de la manette.",
"lambdacontrols.tooltip.fly_drifting": "Pendant que le joueur vole, active le glissement.", "lambdacontrols.tooltip.fly_drifting": "Pendant que le joueur vole, active le glissement Vanilla.",
"lambdacontrols.tooltip.fly_drifting_vertical": "Pendant que le joueur vole, active le glissement vertical.", "lambdacontrols.tooltip.fly_drifting_vertical": "Pendant que le joueur vole, active le glissement vertical Vanilla.",
"lambdacontrols.tooltip.front_block_placing": "Active le placement avant de blocs, §cpeut être considérer comme de la trice sur certains serveurs§r.", "lambdacontrols.tooltip.front_block_placing": "Active le placement avant de blocs, §cpeut être considérer comme de la trice sur certains serveurs§r.",
"lambdacontrols.tooltip.hud_enable": "Détermine si l'indicateur des buttons de la manette doit être affiché ou non.", "lambdacontrols.tooltip.hud_enable": "Détermine si l'indicateur des buttons de la manette doit être affiché ou non.",
"lambdacontrols.tooltip.hud_side": "Change la position du HUD.", "lambdacontrols.tooltip.hud_side": "Change la position du HUD.",
"lambdacontrols.tooltip.mouse_speed": "Change la vitesse de la souris émulée par la manette.", "lambdacontrols.tooltip.mouse_speed": "Change la vitesse de la souris émulée par la manette.",
"lambdacontrols.tooltip.rotation_speed": "Change la vitesse de rotation de la caméra.", "lambdacontrols.tooltip.rotation_speed": "Change la vitesse de rotation de la caméra.",
"lambdacontrols.tooltip.reload_controller_mappings": "Recharge le fichier de configuration des manettes.", "lambdacontrols.tooltip.reload_controller_mappings": "Recharge le fichier de configuration des manettes.",
"lambdacontrols.tooltip.unfocused_input": "Autorise les entrées manette quand la fenêtre n'est pas sélectionnée." "lambdacontrols.tooltip.unfocused_input": "Autorise les entrées manette quand la fenêtre n'est pas sélectionnée.",
"lambdacontrols.tooltip.virtual_mouse": "Active la souris virtuelle qui est pratique dans le cas d'un écran partagé.",
"lambdacontrols.virtual_mouse.skin.default_light": "défaut clair",
"lambdacontrols.virtual_mouse.skin.default_dark": "défaut foncé",
"lambdacontrols.virtual_mouse.skin.second_light": "second clair",
"lambdacontrols.virtual_mouse.skin.second_dark": "second foncé"
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -13,14 +13,21 @@ auto_switch_mode = false
# Gameplay settings # Gameplay settings
[gameplay] [gameplay]
# Enables front block placing like in Bedrock Edition. # Enables fast block placing like in Bedrock Edition.
front_block_placing = false fast_block_placing = true
# Fly behaviors # Fly behaviors
[gameplay.fly] [gameplay.fly]
# Enables fly drifting. # Enables fly drifting.
drifting = false drifting = false
# Enables vertical fly drifting. # Enables vertical fly drifting.
vertical_drifting = true vertical_drifting = true
[gameplay.front_block_placing]
# Enables front block placing like in Bedrock Edition.
enabled = false
# Enables front block placing outline.
outline = true
# The color in a hexadecimal format of the outline.
outline_color = "#ffffff66"
# Controller settings # Controller settings
[controller] [controller]
@@ -33,7 +40,7 @@ auto_switch_mode = false
# Controller's dead zone. # Controller's dead zone.
dead_zone = 0.20 dead_zone = 0.20
# Rotation speed for look directions. # Rotation speed for look directions.
rotation_speed = 40.0 rotation_speed = 10.0
# Mouse speed in GUI. # Mouse speed in GUI.
mouse_speed = 30.0 mouse_speed = 30.0
# Inverts the right X axis. # Inverts the right X axis.
@@ -42,6 +49,10 @@ auto_switch_mode = false
invert_right_y_axis = false invert_right_y_axis = false
# Allow unfocused input. # Allow unfocused input.
unfocused_input = false unfocused_input = false
# Virtual mouse.
virtual_mouse = false
# Virtual mouse skin
virtual_mouse_skin = "default_light"
# Controller controls. # Controller controls.
[controller.controls] [controller.controls]
# Attack control. # Attack control.
@@ -88,10 +99,10 @@ auto_switch_mode = false
sprint = "9" sprint = "9"
# Swap hands control. # Swap hands control.
swap_hands = "2" swap_hands = "2"
# Switch to left tab control. # Switch to back tab control.
tab_left = "4" tab_back = "4"
# Switch to right tab control. # Switch to next tab control.
tab_right = "5" tab_next = "5"
# Toggle perspective control. # Toggle perspective control.
toggle_perspective = "11+3" toggle_perspective = "11+3"
# Toggle smooth camera control. # Toggle smooth camera control.

View File

@@ -27,22 +27,32 @@
] ]
}, },
"mixins": [ "mixins": [
"lambdacontrols.mixins.json" "lambdacontrols.mixins.json",
"lambdacontrols_compat.mixins.json"
], ],
"depends": { "depends": {
"fabricloader": ">=0.4.0", "fabricloader": ">=0.8.0",
"fabric": "*", "fabric": "*",
"minecraft": "1.15.x", "minecraft": ">=1.16",
"spruceui": ">=1.3.4" "spruceui": ">=1.5.2"
}, },
"recommends": { "recommends": {
"modmenu": ">=1.8.0+build.16", "modmenu": ">=1.12.2",
"okzoomer": ">=1.0.4" "okzoomer": ">=4.0.0"
}, },
"suggests": { "suggests": {
"flamingo": "*" "flamingo": "*",
"roughlyenoughitems": ">=4.5.5"
},
"breaks": {
"modmenu": "<1.12.2",
"optifabric": "*"
}, },
"custom": { "custom": {
"modmenu:clientsideOnly": true "modmenu:clientsideOnly": true,
"modupdater": {
"strategy": "curseforge",
"projectID": 354231
}
} }
} }

View File

@@ -5,17 +5,20 @@
"client": [ "client": [
"AbstractButtonWidgetAccessor", "AbstractButtonWidgetAccessor",
"AdvancementsScreenAccessor", "AdvancementsScreenAccessor",
"ContainerScreenMixin",
"ClientPlayerEntityMixin", "ClientPlayerEntityMixin",
"ClientPlayNetworkHandlerMixin", "ClientPlayNetworkHandlerMixin",
"ControlsOptionsScreenMixin", "ControlsOptionsScreenMixin",
"CreativeInventoryScreenAccessor", "CreativeInventoryScreenAccessor",
"EntryListWidgetAccessor", "EntryListWidgetAccessor",
"GameOptionsMixin",
"GameRendererMixin", "GameRendererMixin",
"HandledScreenMixin",
"KeyBindingMixin", "KeyBindingMixin",
"MinecraftClientMixin", "MinecraftClientMixin",
"MouseMixin", "MouseMixin",
"SettingsScreenMixin" "OptionsScreenMixin",
"RecipeBookWidgetAccessor",
"WorldRendererMixin"
], ],
"injectors": { "injectors": {
"defaultRequire": 1 "defaultRequire": 1

View File

@@ -0,0 +1,13 @@
{
"required": true,
"package": "me.lambdaurora.lambdacontrols.client.compat.mixin",
"plugin": "me.lambdaurora.lambdacontrols.client.compat.LambdaControlsMixinPlugin",
"compatibilityLevel": "JAVA_8",
"client": [
"RecipeViewingScreenAccessor",
"VillagerRecipeViewingScreenAccessor"
],
"injectors": {
"defaultRequire": 1
}
}

View File

@@ -3,17 +3,17 @@ org.gradle.jvmargs=-Xmx1G
# Fabric Properties # Fabric Properties
# check these on https://fabricmc.net/use # check these on https://fabricmc.net/use
minecraft_version=1.15.2 minecraft_version=1.16.1
yarn_mappings=1.15.2+build.9:v2 yarn_mappings=1.16.1+build.9:v2
loader_version=0.7.6+build.180 loader_version=0.8.8+build.202
# Mod Properties # Mod Properties
mod_version = 1.1.0 mod_version = 1.3.1
maven_group = me.lambdaurora maven_group = me.lambdaurora.lambdacontrols
archives_base_name = lambdacontrols archives_base_name = lambdacontrols
# Dependencies # Dependencies
# currently not on the main fabric site, check on the maven: https://maven.fabricmc.net/net/fabricmc/fabric-api/fabric-api # currently not on the main fabric site, check on the maven: https://maven.fabricmc.net/net/fabricmc/fabric-api/fabric-api
fabric_version=0.4.29+build.290-1.15 fabric_version=0.14.0+build.371-1.16
spruceui_version=1.3.4 spruceui_version=1.5.2
modmenu_version=1.12.2+build.17