🔖 LambdaControls v1.1.0: Chording update.

This commit is contained in:
LambdAurora
2020-02-01 00:44:13 +01:00
parent f56eb9e0ad
commit a64d5c6f32
63 changed files with 3726 additions and 1234 deletions

47
CHANGELOG.md Normal file
View File

@@ -0,0 +1,47 @@
# Changelog
## v1.0.0
:tada: First release! :tada:
- Added controller support.
- Added new controls settings GUI.
- Added experimental touchscreen support.
- Added controller controls GUI.
- Added a lot of options.
- Added key bindings for look around.
- And more!
### v1.0.1
- Fixed tutorial toast to look around not affected by camera movement done with a controller. ([#2](https://github.com/LambdAurora/LambdaControls/issues/2))
### v1.0.2 (Unofficial)
This update was never pushed but was aiming to fix [#4](https://github.com/LambdAurora/LambdaControls/issues/4).
- Fixed the toggle sneak button binding.
- Fixed broken chat arrow keys.
- Optimized a little bit the button indicator. (need more work)
## v1.1.0 - Chording update
This update also has a backport 1.14.4 version ([#9](https://github.com/LambdAurora/LambdaControls/issues/9)).
- Rewrote everything (almost).
- Added [networking](https://github.com/LambdAurora/LambdaControls/wiki/LambdaControls-Networking) for some features.
- Added second controller support (Joycons supported now hopefully).
- Added chording.
- Added better developer API
- Added hover messages ([#5](https://github.com/LambdAurora/LambdaControls/issues/5)).
- Added hotbar button bindings ([#7](https://github.com/LambdAurora/LambdaControls/issues/7)).
- Added front block placing feature ([#8](https://github.com/LambdAurora/LambdaControls/issues/8)).
- Added no creative fly drifting ([#8](https://github.com/LambdAurora/LambdaControls/issues/8)).
- Added option to enable controller focus.
- Added [OkZoomer](https://github.com/joaoh1/OkZoomer) compatibility.
- Added D-pad movements in inventories.
- Increased max speed ranges.
- Added [SpruceUI](https://github.com/LambdAurora/SpruceUI) for cleaner custom UI widgets.
- Added reset settings button.
- HUD side affects button indicators now.
- Added support for Advancements tabs.

View File

@@ -3,8 +3,39 @@
![Java 8](https://img.shields.io/badge/language-Java%208-9B599A.svg?style=flat-square)
[![GitHub license](https://img.shields.io/github/license/LambdAurora/LambdaControls?style=flat-square)](https://raw.githubusercontent.com/LambdAurora/LambdaControls/master/LICENSE)
![Environment: Client](https://img.shields.io/badge/environment-client-1976d2?style=flat-square)
![Mod loader: Fabric](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)
[![CurseForge](https://cf.way2muchnoise.eu/title/lambdacontrols.svg)](https://www.curseforge.com/minecraft/mc-mods/lambdacontrols)
[![CurseForge](https://cf.way2muchnoise.eu/title/354231.svg)](https://www.curseforge.com/minecraft/mc-mods/lambdacontrols)
A Fabric Minecraft mod which adds better controls.
It allows the use of a controller or the touchscreen.
A Fabric Minecraft mod which adds better controls like controller support.
## What's this mod?
Haven't you dreamed to travel in your modded Minecraft world with your controller? Yes? Then this mod is made for you!
This mod adds a controller support (and an experimental touchscreen support).
## ✅ Features:
- Controller support
- Touchscreen support (very experimental and buggy).
- Keyboard controls to look around.
- Toggleable on screen button indicator (like in Bedrock Edition).
- Many Bedrock Edition features:
- Toggleable fly drifting
- Front block placing (be careful with this one)
- New controls settings!
- Many options in config to change to your liking.
- Many controllers supported and in a simply way your own controller mappings.
## 🎮 Supported Controllers:
- Dualshock controllers
- Xbox controllers
- Switch Pro controllers
- Joycons
- And many more!
## Build
Just do `./gradlew :fabric:build` and everything should build just fine!

View File

@@ -6,7 +6,7 @@ archivesBaseName = project.archives_base_name + "-core"
dependencies {
api "org.jetbrains:annotations:17.0.0"
api "org.aperlambda:lambdajcommon:1.7.2"
api "org.aperlambda:lambdajcommon:1.8.0"
api "com.electronwill.night-config:core:3.5.3"
api "com.electronwill.night-config:toml:3.5.3"
}

View File

@@ -47,13 +47,13 @@ public enum ControlsMode implements Nameable
* @return The translated key of this controls mode.
* @since 1.1.0
*/
public String get_translation_key()
public String getTranslationKey()
{
return "lambdacontrols.controls_mode." + this.get_name();
return "lambdacontrols.controls_mode." + this.getName();
}
@Override
public @NotNull String get_name()
public @NotNull String getName()
{
return this.name().toLowerCase();
}
@@ -64,8 +64,8 @@ public enum ControlsMode implements Nameable
* @param id The identifier of the controls mode.
* @return The controls mode if found, else empty.
*/
public static Optional<ControlsMode> by_id(@NotNull String id)
public static Optional<ControlsMode> byId(@NotNull String id)
{
return Arrays.stream(values()).filter(mode -> mode.get_name().equalsIgnoreCase(id)).findFirst();
return Arrays.stream(values()).filter(mode -> mode.getName().equalsIgnoreCase(id)).findFirst();
}
}

View File

@@ -9,6 +9,8 @@
package me.lambdaurora.lambdacontrols;
import org.aperlambda.lambdacommon.Identifier;
/**
* Represents the constants used by LambdaControls.
*
@@ -18,5 +20,8 @@ package me.lambdaurora.lambdacontrols;
*/
public class LambdaControlsConstants
{
public static final String NAMESPACE = "lambdacontrols";
public static final String NAMESPACE = "lambdacontrols";
public static final Identifier CONTROLS_MODE_CHANNEL = new Identifier(NAMESPACE, "controls_mode");
public static final Identifier FEATURE_CHANNEL = new Identifier(NAMESPACE, "feature");
public static final Identifier HELLO_CHANNEL = new Identifier(NAMESPACE, "hello");
}

View File

@@ -0,0 +1,159 @@
/*
* 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;
import org.aperlambda.lambdacommon.utils.Nameable;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
/**
* Represents a feature.
*
* @author LambdAurora
* @version 1.1.0
* @since 1.1.0
*/
public class LambdaControlsFeature implements Nameable
{
private static final List<LambdaControlsFeature> FEATURES = new ArrayList<>();
public static final LambdaControlsFeature FRONT_BLOCK_PLACING = new LambdaControlsFeature("front_block_placing", true, false);
private final String key;
private final boolean defaultAllowed;
private boolean allowed;
private final boolean defaultEnabled;
private boolean enabled;
public LambdaControlsFeature(@NotNull String key, boolean allowed, boolean enabled)
{
Objects.requireNonNull(key, "Feature key cannot be null.");
this.key = key;
this.setAllowed(this.defaultAllowed = allowed);
this.setEnabled(this.defaultEnabled = enabled);
}
public LambdaControlsFeature(@NotNull String key)
{
this(key, false, false);
}
/**
* Allows the feature.
*/
public void allow()
{
this.setAllowed(true);
}
/**
* Returns whether this feature is allowed.
*
* @return True if this feature is allowed, else false.
*/
public boolean isAllowed()
{
return this.allowed;
}
/**
* Sets whether this feature is allowed.
*
* @param allowed True if this feature is allowed, else false.
*/
public void setAllowed(boolean allowed)
{
this.allowed = allowed;
}
/**
* Resets allowed state to default.
*/
public void resetAllowed()
{
this.setAllowed(this.defaultAllowed);
}
/**
* Returns whether this feature is enabled.
*
* @return True if this feature is enabled, else false.
*/
public boolean isEnabled()
{
return this.enabled;
}
/**
* Returns whether this feature is enabled.
*
* @param enabled True if this feature is enabled, else false.
*/
public void setEnabled(boolean enabled)
{
this.enabled = enabled;
}
/**
* Returns whether this feature is available or not.
*
* @return True if this feature is available, else false.
* @see #isAllowed()
* @see #isEnabled()
*/
public boolean isAvailable()
{
return this.isAllowed() && this.isEnabled();
}
/**
* Resets the feature to its default values.
*/
public void reset()
{
this.resetAllowed();
this.setEnabled(this.defaultEnabled);
}
@Override
public @NotNull String getName()
{
return this.key;
}
public static @NotNull Optional<LambdaControlsFeature> fromName(@NotNull String key)
{
Objects.requireNonNull(key, "Cannot find features with a null name.");
return FEATURES.parallelStream().filter(feature -> feature.getName().equals(key)).findFirst();
}
/**
* Resets all features to their default values.
*/
public static void resetAll()
{
FEATURES.parallelStream().forEach(LambdaControlsFeature::reset);
}
/**
* Resets all features to allow state.
*/
public static void resetAllAllowed()
{
FEATURES.parallelStream().forEach(LambdaControlsFeature::resetAllowed);
}
static {
FEATURES.add(FRONT_BLOCK_PLACING);
}
}

View File

@@ -27,12 +27,12 @@ import org.mcelytra.core.event.player.PlayerEvent;
public class PlayerControlsModeEvent extends PlayerEvent
{
private static final HandlerList HANDLERS = new HandlerList();
private final ControlsMode controls_mode;
private final ControlsMode controlsMode;
public PlayerControlsModeEvent(@NotNull EntityPlayer player, @NotNull ControlsMode controls_mode)
public PlayerControlsModeEvent(@NotNull EntityPlayer player, @NotNull ControlsMode controlsMode)
{
super(new Identifier(LambdaControlsConstants.NAMESPACE, "player_controls_mode"), player, true);
this.controls_mode = controls_mode;
this.controlsMode = controlsMode;
}
/**
@@ -40,13 +40,13 @@ public class PlayerControlsModeEvent extends PlayerEvent
*
* @return The player's controls mode.
*/
public ControlsMode get_controls_mode()
public ControlsMode getControlsMode()
{
return this.controls_mode;
return this.controlsMode;
}
@Override
public @NotNull HandlerList get_handlers()
public @NotNull HandlerList getHandlers()
{
return HANDLERS;
}

View File

@@ -42,17 +42,20 @@ dependencies {
// Fabric API. This is technically optional, but you probably want it anyway.
modApi "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
modCompile "io.github.prospector:modmenu:1.8.0+build.16"
modCompile "io.github.prospector:modmenu:1.8.5+build.23"
modCompile "com.github.lambdaurora:spruceui:${project.spruceui_version}"
include "com.github.lambdaurora:spruceui:${project.spruceui_version}"
// Compatibility mods
modCompile "io.github.joaoh1:okzoomer:2.0.1"
modCompile "io.github.joaoh1:okzoomer:2.1.0-beta.2"
api project(":core")
shadow project(":core")
include "org.jetbrains:annotations:17.0.0"
include "org.aperlambda:lambdajcommon:1.7.2"
include("org.aperlambda:lambdajcommon:1.8.0") {
exclude group: 'com.google.code.gson'
exclude group: 'com.google.guava'
}
include "com.electronwill.night-config:core:3.5.3"
include "com.electronwill.night-config:toml:3.5.3"
}

View File

@@ -9,12 +9,20 @@
package me.lambdaurora.lambdacontrols;
import io.netty.buffer.Unpooled;
import me.lambdaurora.lambdacontrols.event.PlayerChangeControlsModeCallback;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.network.ServerSidePacketRegistry;
import net.fabricmc.loader.api.FabricLoader;
import net.fabricmc.loader.api.ModContainer;
import net.minecraft.util.Identifier;
import net.minecraft.util.PacketByteBuf;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jetbrains.annotations.NotNull;
import java.util.Objects;
import java.util.Optional;
/**
* Represents the LambdaControls mod.
@@ -26,7 +34,9 @@ import org.apache.logging.log4j.Logger;
public class LambdaControls implements ModInitializer
{
private static LambdaControls INSTANCE;
public static final Identifier CONTROLS_MODE_CHANNEL = new Identifier(LambdaControlsConstants.NAMESPACE, "controls_mode");
public static final Identifier CONTROLS_MODE_CHANNEL = new Identifier(LambdaControlsConstants.CONTROLS_MODE_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 final Logger logger = LogManager.getLogger("LambdaControls");
@@ -36,10 +46,19 @@ public class LambdaControls implements ModInitializer
INSTANCE = this;
this.log("Initializing LambdaControls...");
ServerSidePacketRegistry.INSTANCE.register(HELLO_CHANNEL,
(context, attachedData) -> {
String version = attachedData.readString(16);
ControlsMode.byId(attachedData.readString(32))
.ifPresent(controlsMode -> context.getTaskQueue()
.execute(() -> PlayerChangeControlsModeCallback.EVENT.invoker().apply(context.getPlayer(), controlsMode)));
context.getTaskQueue().execute(() ->
ServerSidePacketRegistry.INSTANCE.sendToPlayer(context.getPlayer(), FEATURE_CHANNEL, this.makeFeatureBuffer(LambdaControlsFeature.FRONT_BLOCK_PLACING)));
});
ServerSidePacketRegistry.INSTANCE.register(CONTROLS_MODE_CHANNEL,
(context, attached_data) -> ControlsMode.by_id(attached_data.readString(32))
.ifPresent(controls_mode -> context.getTaskQueue()
.execute(() -> PlayerChangeControlsModeCallback.EVENT.invoker().apply(context.getPlayer(), controls_mode))));
(context, attachedData) -> ControlsMode.byId(attachedData.readString(32))
.ifPresent(controlsMode -> context.getTaskQueue()
.execute(() -> PlayerChangeControlsModeCallback.EVENT.invoker().apply(context.getPlayer(), controlsMode))));
}
/**
@@ -62,6 +81,42 @@ public class LambdaControls implements ModInitializer
this.logger.info("[LambdaControls] " + warning);
}
/**
* Returns a packet byte buffer made for the lambdacontrols:controls_mode plugin message.
*
* @param controlsMode The controls mode to send.
* @return The packet byte buffer.
*/
public PacketByteBuf makeControlsModeBuffer(@NotNull ControlsMode controlsMode)
{
Objects.requireNonNull(controlsMode, "Controls mode cannot be null.");
return new PacketByteBuf(Unpooled.buffer()).writeString(controlsMode.getName(), 32);
}
/**
* Returns a packet byte buffer made for the lambdacontrols:feature plugin message.
*
* @param feature The feature data to send.
* @return The packet byte buffer.
*/
public PacketByteBuf makeFeatureBuffer(@NotNull LambdaControlsFeature feature)
{
Objects.requireNonNull(feature, "Feature cannot be null.");
PacketByteBuf buffer = new PacketByteBuf(Unpooled.buffer()).writeString(feature.getName(), 64);
buffer.writeBoolean(feature.isAllowed());
return buffer;
}
public PacketByteBuf makeHello(@NotNull ControlsMode controlsMode)
{
String version = "";
Optional<ModContainer> container;
if ((container = FabricLoader.getInstance().getModContainer(LambdaControlsConstants.NAMESPACE)).isPresent()) {
version = container.get().getMetadata().getVersion().getFriendlyString();
}
return new PacketByteBuf(Unpooled.buffer()).writeString(version, 16).writeString(controlsMode.getName(), 32);
}
/**
* Gets the LambdaControls instance.
*

View File

@@ -35,7 +35,7 @@ public enum ButtonState
*
* @return True if this state is a pressed state, else false.
*/
public boolean is_pressed()
public boolean isPressed()
{
return this == PRESS || this == REPEAT;
}
@@ -45,7 +45,7 @@ public enum ButtonState
*
* @return True if this state is an unpressed state, else false.
*/
public boolean is_unpressed()
public boolean isUnpressed()
{
return this == RELEASE || this == NONE;
}

View File

@@ -44,7 +44,7 @@ public enum ControllerType implements Nameable
*
* @return The controller type's identifier.
*/
public int get_id()
public int getId()
{
return this.id;
}
@@ -67,13 +67,13 @@ public enum ControllerType implements Nameable
*
* @return The translated name of this controller type.
*/
public String get_translated_name()
public String getTranslatedName()
{
return I18n.translate("lambdacontrols.controller_type." + this.get_name());
return I18n.translate("lambdacontrols.controller_type." + this.getName());
}
@Override
public @NotNull String get_name()
public @NotNull String getName()
{
return this.name().toLowerCase();
}
@@ -84,8 +84,8 @@ public enum ControllerType implements Nameable
* @param id The identifier of the controller type.
* @return The controller type if found, else empty.
*/
public static Optional<ControllerType> by_id(@NotNull String id)
public static Optional<ControllerType> byId(@NotNull String id)
{
return Arrays.stream(values()).filter(mode -> mode.get_name().equalsIgnoreCase(id)).findFirst();
return Arrays.stream(values()).filter(mode -> mode.getName().equalsIgnoreCase(id)).findFirst();
}
}

View File

@@ -46,13 +46,13 @@ public enum HudSide implements Nameable
*
* @return The translated name of this hud side.
*/
public String get_translated_name()
public String getTranslatedName()
{
return I18n.translate("lambdacontrols.hud_side." + this.get_name());
return I18n.translate("lambdacontrols.hud_side." + this.getName());
}
@Override
public @NotNull String get_name()
public @NotNull String getName()
{
return this.name().toLowerCase();
}
@@ -63,8 +63,8 @@ public enum HudSide implements Nameable
* @param id The identifier of the hud side.
* @return The hud side if found, else empty.
*/
public static Optional<HudSide> by_id(@NotNull String id)
public static Optional<HudSide> byId(@NotNull String id)
{
return Arrays.stream(values()).filter(mode -> mode.get_name().equalsIgnoreCase(id)).findFirst();
return Arrays.stream(values()).filter(mode -> mode.getName().equalsIgnoreCase(id)).findFirst();
}
}

View File

@@ -13,14 +13,19 @@ import com.mojang.blaze3d.platform.GlStateManager;
import me.lambdaurora.lambdacontrols.ControlsMode;
import me.lambdaurora.lambdacontrols.LambdaControls;
import me.lambdaurora.lambdacontrols.LambdaControlsConstants;
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.Controller;
import me.lambdaurora.lambdacontrols.client.gui.LambdaControlsHud;
import me.lambdaurora.lambdacontrols.client.gui.TouchscreenOverlay;
import me.lambdaurora.spruceui.event.OpenScreenCallback;
import me.lambdaurora.spruceui.hud.HudManager;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.fabric.api.client.keybinding.FabricKeyBinding;
import net.fabricmc.fabric.api.client.keybinding.KeyBindingRegistry;
import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback;
import net.fabricmc.fabric.api.event.client.ClientTickCallback;
import net.fabricmc.fabric.api.network.ClientSidePacketRegistry;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.DrawableHelper;
@@ -57,7 +62,7 @@ public class LambdaControlsClient extends LambdaControls implements ClientModIni
public final LambdaControlsConfig config = new LambdaControlsConfig(this);
public final LambdaInput input = new LambdaInput(this);
private LambdaControlsHud hud;
private ControlsMode previous_controls_mode;
private ControlsMode previousControlsMode;
@Override
public void onInitializeClient()
@@ -68,32 +73,52 @@ public class LambdaControlsClient extends LambdaControls implements ClientModIni
KeyBindingRegistry.INSTANCE.register(BINDING_LOOK_DOWN);
KeyBindingRegistry.INSTANCE.register(BINDING_LOOK_LEFT);
HudRenderCallback.EVENT.register(delta -> this.hud.render());
ClientSidePacketRegistry.INSTANCE.register(CONTROLS_MODE_CHANNEL, (context, attachedData) -> context.getTaskQueue()
.execute(() -> ClientSidePacketRegistry.INSTANCE.sendToServer(CONTROLS_MODE_CHANNEL, this.makeControlsModeBuffer(this.config.getControlsMode()))));
ClientSidePacketRegistry.INSTANCE.register(FEATURE_CHANNEL, (context, attachedData) -> {
String name = attachedData.readString(64);
boolean allowed = attachedData.readBoolean();
LambdaControlsFeature.fromName(name).ifPresent(feature -> context.getTaskQueue().execute(() -> feature.setAllowed(allowed)));
});
ClientTickCallback.EVENT.register(this::onTick);
OpenScreenCallback.EVENT.register((client, screen) -> {
if (screen == null && this.config.getControlsMode() == ControlsMode.TOUCHSCREEN) {
screen = new TouchscreenOverlay(this);
screen.init(client, client.getWindow().getScaledWidth(), client.getWindow().getScaledHeight());
client.skipGameRender = false;
client.currentScreen = screen;
} else if (screen != null) {
this.input.onScreenOpen(client, client.getWindow().getWidth(), client.getWindow().getHeight());
}
});
HudManager.register(this.hud = new LambdaControlsHud(this));
}
/**
* This method is called when Minecraft is initializing.
*/
public void on_mc_init(@NotNull MinecraftClient client)
public void onMcInit(@NotNull MinecraftClient client)
{
ButtonBinding.init(client.options);
this.config.load();
Controller.update_mappings();
this.hud.setVisible(this.config.isHudEnabled());
Controller.updateMappings();
GLFW.glfwSetJoystickCallback((jid, event) -> {
if (event == GLFW.GLFW_CONNECTED) {
Controller controller = Controller.by_id(jid);
Controller controller = Controller.byId(jid);
client.getToastManager().add(new SystemToast(SystemToast.Type.TUTORIAL_HINT, new TranslatableText("lambdacontrols.controller.connected", jid),
new LiteralText(controller.get_name())));
new LiteralText(controller.getName())));
} else if (event == GLFW.GLFW_DISCONNECTED) {
client.getToastManager().add(new SystemToast(SystemToast.Type.TUTORIAL_HINT, new TranslatableText("lambdacontrols.controller.disconnected", jid),
null));
}
this.switch_controls_mode();
this.switchControlsMode();
});
this.hud = new LambdaControlsHud(client, this);
LambdaControlsCompat.init(this);
}
@@ -102,37 +127,56 @@ public class LambdaControlsClient extends LambdaControls implements ClientModIni
*
* @param client The client instance.
*/
public void on_tick(@NotNull MinecraftClient client)
public void onTick(@NotNull MinecraftClient client)
{
this.input.on_tick(client);
if (this.config.get_controls_mode() == ControlsMode.CONTROLLER && (client.isWindowFocused() || this.config.has_unfocused_input()))
this.input.on_controller_tick(client);
this.input.onTick(client);
if (this.config.getControlsMode() == ControlsMode.CONTROLLER && (client.isWindowFocused() || this.config.hasUnfocusedInput()))
this.input.onControllerTick(client);
}
public void on_render(MinecraftClient client)
public void onRender(MinecraftClient client)
{
this.input.on_render(client);
this.input.onRender(client);
}
/**
* Called when leaving a server.
*/
public void onLeave()
{
LambdaControlsFeature.resetAllAllowed();
}
/**
* Switches the controls mode if the auto switch is enabled.
*/
public void switch_controls_mode()
public void switchControlsMode()
{
if (this.config.has_auto_switch_mode()) {
if (this.config.get_controller().is_gamepad()) {
this.previous_controls_mode = this.config.get_controls_mode();
this.config.set_controls_mode(ControlsMode.CONTROLLER);
if (this.config.hasAutoSwitchMode()) {
if (this.config.getController().isGamepad()) {
this.previousControlsMode = this.config.getControlsMode();
this.config.setControlsMode(ControlsMode.CONTROLLER);
} else {
if (this.previous_controls_mode == null) {
this.previous_controls_mode = ControlsMode.DEFAULT;
if (this.previousControlsMode == null) {
this.previousControlsMode = ControlsMode.DEFAULT;
}
this.config.set_controls_mode(this.previous_controls_mode);
this.config.setControlsMode(this.previousControlsMode);
}
}
}
/**
* Sets whether the HUD is enabled or not.
*
* @param enabled True if the HUD is enabled, else false.
*/
public void setHudEnabled(boolean enabled)
{
this.config.setHudEnabled(enabled);
this.hud.setVisible(enabled);
}
/**
* Gets the LambdaControls client instance.
*
@@ -143,31 +187,32 @@ public class LambdaControlsClient extends LambdaControls implements ClientModIni
return INSTANCE;
}
public static Pair<Integer, Integer> draw_button(int x, int y, @NotNull ButtonBinding button, @NotNull MinecraftClient client)
public static Pair<Integer, Integer> drawButton(int x, int y, @NotNull ButtonBinding button, @NotNull MinecraftClient client)
{
return draw_button(x, y, button.get_button(), client);
return drawButton(x, y, button.getButton(), client);
}
public static Pair<Integer, Integer> draw_button(int x, int y, int[] buttons, @NotNull MinecraftClient client)
public static Pair<Integer, Integer> drawButton(int x, int y, int[] buttons, @NotNull MinecraftClient client)
{
int height = 0;
int length = 0;
int current_x = x;
int currentX = x;
for (int i = 0; i < buttons.length; i++) {
int btn = buttons[i];
Pair<Integer, Integer> size = draw_button(current_x, y, btn, client);
if (size.get_key() > height)
height = size.get_value();
length += size.get_key();
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;
current_x = x + length;
currentX = x + length;
}
}
return Pair.of(length, height);
}
public static Pair<Integer, Integer> draw_button(int x, int y, int button, @NotNull MinecraftClient client)
@SuppressWarnings("deprecated")
public static Pair<Integer, Integer> drawButton(int x, int y, int button, @NotNull MinecraftClient client)
{
boolean second = false;
if (button == -1)
@@ -177,70 +222,70 @@ public class LambdaControlsClient extends LambdaControls implements ClientModIni
second = true;
}
int controller_type = get().config.get_controller_type().get_id();
int controllerType = get().config.getControllerType().getId();
boolean axis = false;
int button_offset = button * 15;
int buttonOffset = button * 15;
switch (button) {
case GLFW.GLFW_GAMEPAD_BUTTON_LEFT_BUMPER:
button_offset = 7 * 15;
buttonOffset = 7 * 15;
break;
case GLFW.GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER:
button_offset = 8 * 15;
buttonOffset = 8 * 15;
break;
case GLFW.GLFW_GAMEPAD_BUTTON_BACK:
button_offset = 4 * 15;
buttonOffset = 4 * 15;
break;
case GLFW.GLFW_GAMEPAD_BUTTON_START:
button_offset = 6 * 15;
buttonOffset = 6 * 15;
break;
case GLFW.GLFW_GAMEPAD_BUTTON_GUIDE:
button_offset = 5 * 15;
buttonOffset = 5 * 15;
break;
case GLFW.GLFW_GAMEPAD_BUTTON_LEFT_THUMB:
button_offset = 15 * 15;
buttonOffset = 15 * 15;
break;
case GLFW.GLFW_GAMEPAD_BUTTON_RIGHT_THUMB:
button_offset = 16 * 15;
buttonOffset = 16 * 15;
break;
case GLFW.GLFW_GAMEPAD_AXIS_LEFT_X + 100:
button_offset = 0;
buttonOffset = 0;
axis = true;
break;
case GLFW.GLFW_GAMEPAD_AXIS_LEFT_Y + 100:
button_offset = 18;
buttonOffset = 18;
axis = true;
break;
case GLFW.GLFW_GAMEPAD_AXIS_RIGHT_X + 100:
button_offset = 2 * 18;
buttonOffset = 2 * 18;
axis = true;
break;
case GLFW.GLFW_GAMEPAD_AXIS_RIGHT_Y + 100:
button_offset = 3 * 18;
buttonOffset = 3 * 18;
axis = true;
break;
case GLFW.GLFW_GAMEPAD_AXIS_LEFT_X + 200:
button_offset = 4 * 18;
buttonOffset = 4 * 18;
axis = true;
break;
case GLFW.GLFW_GAMEPAD_AXIS_LEFT_Y + 200:
button_offset = 5 * 18;
buttonOffset = 5 * 18;
axis = true;
break;
case GLFW.GLFW_GAMEPAD_AXIS_RIGHT_X + 200:
button_offset = 6 * 18;
buttonOffset = 6 * 18;
axis = true;
break;
case GLFW.GLFW_GAMEPAD_AXIS_RIGHT_Y + 200:
button_offset = 7 * 18;
buttonOffset = 7 * 18;
axis = true;
break;
case GLFW.GLFW_GAMEPAD_AXIS_LEFT_TRIGGER + 100:
case GLFW.GLFW_GAMEPAD_AXIS_LEFT_TRIGGER + 200:
button_offset = 9 * 15;
buttonOffset = 9 * 15;
break;
case GLFW.GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER + 100:
case GLFW.GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER + 200:
button_offset = 10 * 15;
buttonOffset = 10 * 15;
break;
}
@@ -248,34 +293,34 @@ public class LambdaControlsClient extends LambdaControls implements ClientModIni
GlStateManager.disableDepthTest();
GlStateManager.color4f(1.0F, second ? 0.0F : 1.0F, 1.0F, 1.0F);
DrawableHelper.blit(x, y, (float) button_offset, (float) (controller_type * (axis ? 18 : 15)), axis ? 18 : 15, axis ? 18 : 15, 256, 256);
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 draw_button_tip(int x, int y, @NotNull ButtonBinding button, boolean display, @NotNull MinecraftClient client)
public static int drawButtonTip(int x, int y, @NotNull ButtonBinding button, boolean display, @NotNull MinecraftClient client)
{
return draw_button_tip(x, y, button.get_button(), button.get_translation_key(), display, client);
return drawButtonTip(x, y, button.getButton(), button.getTranslationKey(), display, client);
}
public static int draw_button_tip(int x, int y, int[] button, @NotNull String action, boolean display, @NotNull MinecraftClient client)
public static int drawButtonTip(int x, int y, int[] button, @NotNull String action, boolean display, @NotNull MinecraftClient client)
{
if (display) {
int button_width = draw_button(x, y, button, client).get_key();
int buttonWidth = drawButton(x, y, button, client).key;
String translated_action = I18n.translate(action);
int text_y = (15 - client.textRenderer.fontHeight) / 2;
client.textRenderer.drawWithShadow(translated_action, (float) (x + button_width + 5), (float) (y + text_y), 14737632);
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 get_button_tip_width(translated_action, client.textRenderer);
return getButtonTipWidth(translatedAction, client.textRenderer);
}
return -10;
}
private static int get_button_tip_width(@NotNull String action, @NotNull TextRenderer text_renderer)
private static int getButtonTipWidth(@NotNull String action, @NotNull TextRenderer textRenderer)
{
return 15 + 5 + text_renderer.getStringWidth(action);
return 15 + 5 + textRenderer.getStringWidth(action);
}
}

View File

@@ -11,6 +11,7 @@ package me.lambdaurora.lambdacontrols.client;
import com.electronwill.nightconfig.core.file.FileConfig;
import me.lambdaurora.lambdacontrols.ControlsMode;
import me.lambdaurora.lambdacontrols.LambdaControlsFeature;
import me.lambdaurora.lambdacontrols.client.controller.ButtonBinding;
import me.lambdaurora.lambdacontrols.client.controller.Controller;
import me.lambdaurora.lambdacontrols.client.controller.InputManager;
@@ -33,35 +34,36 @@ import static org.lwjgl.glfw.GLFW.GLFW_GAMEPAD_AXIS_LEFT_Y;
public class LambdaControlsConfig
{
// General
private static final ControlsMode DEFAULT_CONTROLS_MODE = ControlsMode.DEFAULT;
private static final boolean DEFAULT_AUTO_SWITCH_MODE = false;
private static final ControlsMode DEFAULT_CONTROLS_MODE = ControlsMode.DEFAULT;
private static final boolean DEFAULT_AUTO_SWITCH_MODE = false;
// HUD
private static final boolean DEFAULT_HUD_ENABLE = true;
private static final HudSide DEFAULT_HUD_SIDE = HudSide.LEFT;
private static final boolean DEFAULT_HUD_ENABLE = true;
private static final HudSide DEFAULT_HUD_SIDE = HudSide.LEFT;
// Gameplay
private static final boolean DEFAULT_FRONT_BLOCK_PLACING = false;
private static final boolean DEFAULT_FLY_DRIFTING = false;
private static final boolean DEFAULT_FRONT_BLOCK_PLACING = false;
private static final boolean DEFAULT_FLY_DRIFTING = false;
private static final boolean DEFAULT_FLY_VERTICAL_DRIFTING = true;
// Controller
private static final ControllerType DEFAULT_CONTROLLER_TYPE = ControllerType.DEFAULT;
private static final double DEFAULT_DEAD_ZONE = 0.25;
private static final double DEFAULT_ROTATION_SPEED = 40.0;
private static final double DEFAULT_MOUSE_SPEED = 25.0;
private static final boolean DEFAULT_UNFOCUSED_INPUT = false;
private static final ControllerType DEFAULT_CONTROLLER_TYPE = ControllerType.DEFAULT;
private static final double DEFAULT_DEAD_ZONE = 0.25;
private static final double DEFAULT_ROTATION_SPEED = 40.0;
private static final double DEFAULT_MOUSE_SPEED = 25.0;
private static final boolean DEFAULT_UNFOCUSED_INPUT = false;
private static final Pattern BUTTON_BINDING_PATTERN = Pattern.compile("(-?\\d+)\\+?");
protected final FileConfig config = FileConfig.builder("config/lambdacontrols.toml").concurrent().defaultResource("/config.toml").build();
private final LambdaControlsClient mod;
private ControlsMode controls_mode;
private ControllerType controller_type;
private ControlsMode controlsMode;
private ControllerType controllerType;
// HUD settings.
private boolean hud_enable;
private HudSide hud_side;
private boolean hudEnable;
private HudSide hudSide;
// Controller settings
private double dead_zone;
private double rotation_speed;
private double mouse_speed;
private boolean unfocused_input;
private double deadZone;
private double rotationSpeed;
private double mouseSpeed;
private boolean unfocusedInput;
public LambdaControlsConfig(@NotNull LambdaControlsClient mod)
{
@@ -74,20 +76,22 @@ public class LambdaControlsConfig
public void load()
{
this.config.load();
this.check_and_fix();
this.checkAndFix();
this.mod.log("Configuration loaded.");
this.controls_mode = ControlsMode.by_id(this.config.getOrElse("controls", DEFAULT_CONTROLS_MODE.get_name())).orElse(DEFAULT_CONTROLS_MODE);
this.controlsMode = ControlsMode.byId(this.config.getOrElse("controls", DEFAULT_CONTROLS_MODE.getName())).orElse(DEFAULT_CONTROLS_MODE);
// HUD settings.
this.hud_enable = this.config.getOrElse("hud.enable", DEFAULT_HUD_ENABLE);
this.hud_side = HudSide.by_id(this.config.getOrElse("hud.side", DEFAULT_HUD_SIDE.get_name())).orElse(DEFAULT_HUD_SIDE);
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);
// Gameplay
LambdaControlsFeature.FRONT_BLOCK_PLACING.setEnabled(this.config.getOrElse("gameplay.front_block_placing", DEFAULT_FRONT_BLOCK_PLACING));
// Controller settings.
this.controller_type = ControllerType.by_id(this.config.getOrElse("controller.type", DEFAULT_CONTROLLER_TYPE.get_name())).orElse(DEFAULT_CONTROLLER_TYPE);
this.dead_zone = this.config.getOrElse("controller.dead_zone", DEFAULT_DEAD_ZONE);
this.rotation_speed = this.config.getOrElse("controller.rotation_speed", DEFAULT_ROTATION_SPEED);
this.mouse_speed = this.config.getOrElse("controller.mouse_speed", DEFAULT_MOUSE_SPEED);
this.unfocused_input = this.config.getOrElse("controller.unfocused_input", DEFAULT_UNFOCUSED_INPUT);
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.rotationSpeed = this.config.getOrElse("controller.rotation_speed", DEFAULT_ROTATION_SPEED);
this.mouseSpeed = this.config.getOrElse("controller.mouse_speed", DEFAULT_MOUSE_SPEED);
this.unfocusedInput = this.config.getOrElse("controller.unfocused_input", DEFAULT_UNFOCUSED_INPUT);
// Controller controls.
InputManager.load_button_bindings(this);
InputManager.loadButtonBindings(this);
}
/**
@@ -95,18 +99,18 @@ public class LambdaControlsConfig
*/
public void save()
{
this.config.set("controller.dead_zone", this.dead_zone);
this.config.set("controller.rotation_speed", this.rotation_speed);
this.config.set("controller.mouse_speed", this.mouse_speed);
this.config.set("controller.unfocused_input", this.unfocused_input);
this.config.set("controller.dead_zone", this.deadZone);
this.config.set("controller.rotation_speed", this.rotationSpeed);
this.config.set("controller.mouse_speed", this.mouseSpeed);
this.config.set("controller.unfocused_input", this.unfocusedInput);
this.config.save();
this.mod.log("Configuration saved.");
}
public void check_and_fix()
public void checkAndFix()
{
InputManager.stream_bindings().forEach(binding -> {
String path = "controller.controls." + binding.get_name();
InputManager.streamBindings().forEach(binding -> {
String path = "controller.controls." + binding.getName();
Object raw = this.config.getRaw(path);
if (raw instanceof Number) {
this.mod.warn("Invalid data at \"" + path + "\", fixing...");
@@ -121,23 +125,24 @@ public class LambdaControlsConfig
public void reset()
{
// General
this.set_controls_mode(DEFAULT_CONTROLS_MODE);
this.set_auto_switch_mode(DEFAULT_AUTO_SWITCH_MODE);
this.setControlsMode(DEFAULT_CONTROLS_MODE);
this.setAutoSwitchMode(DEFAULT_AUTO_SWITCH_MODE);
// HUD
this.set_hud_enabled(DEFAULT_HUD_ENABLE);
this.set_hud_side(DEFAULT_HUD_SIDE);
this.setHudEnabled(DEFAULT_HUD_ENABLE);
this.setHudSide(DEFAULT_HUD_SIDE);
// Gameplay
this.set_front_block_placing(DEFAULT_FRONT_BLOCK_PLACING);
this.set_fly_drifting(DEFAULT_FLY_DRIFTING);
this.setFrontBlockPlacing(DEFAULT_FRONT_BLOCK_PLACING);
this.setFlyDrifting(DEFAULT_FLY_DRIFTING);
this.setFlyVerticalDrifting(DEFAULT_FLY_VERTICAL_DRIFTING);
// Controller
this.set_controller_type(DEFAULT_CONTROLLER_TYPE);
this.set_dead_zone(DEFAULT_DEAD_ZONE);
this.set_rotation_speed(DEFAULT_ROTATION_SPEED);
this.set_mouse_speed(DEFAULT_MOUSE_SPEED);
this.set_unfocused_input(DEFAULT_UNFOCUSED_INPUT);
this.setControllerType(DEFAULT_CONTROLLER_TYPE);
this.setDeadZone(DEFAULT_DEAD_ZONE);
this.setRotationSpeed(DEFAULT_ROTATION_SPEED);
this.setMouseSpeed(DEFAULT_MOUSE_SPEED);
this.setUnfocusedInput(DEFAULT_UNFOCUSED_INPUT);
// Collect prevents concurrent modification.
InputManager.stream_bindings().collect(Collectors.toList()).forEach(binding -> this.set_button_binding(binding, binding.get_default_button()));
InputManager.streamBindings().collect(Collectors.toList()).forEach(binding -> this.setButtonBinding(binding, binding.getDefaultButton()));
}
/**
@@ -145,20 +150,20 @@ public class LambdaControlsConfig
*
* @return The controls mode.
*/
public @NotNull ControlsMode get_controls_mode()
public @NotNull ControlsMode getControlsMode()
{
return this.controls_mode;
return this.controlsMode;
}
/**
* Sets the controls mode in the configuration.
*
* @param controls_mode The controls mode.
* @param controlsMode The controls mode.
*/
public void set_controls_mode(@NotNull ControlsMode controls_mode)
public void setControlsMode(@NotNull ControlsMode controlsMode)
{
this.controls_mode = controls_mode;
this.config.set("controls", controls_mode.get_name());
this.controlsMode = controlsMode;
this.config.set("controls", controlsMode.getName());
}
/**
@@ -166,7 +171,7 @@ public class LambdaControlsConfig
*
* @return True if the auto switch mode is enabled, else false.
*/
public boolean has_auto_switch_mode()
public boolean hasAutoSwitchMode()
{
return this.config.getOrElse("auto_switch_mode", DEFAULT_AUTO_SWITCH_MODE);
}
@@ -174,11 +179,11 @@ public class LambdaControlsConfig
/**
* Sets whether the auto switch mode is enabled or not.
*
* @param auto_switch_mode True if the auto switch mode is enabled, else false.
* @param autoSwitchMode True if the auto switch mode is enabled, else false.
*/
public void set_auto_switch_mode(boolean auto_switch_mode)
public void setAutoSwitchMode(boolean autoSwitchMode)
{
this.config.set("auto_switch_mode", auto_switch_mode);
this.config.set("auto_switch_mode", autoSwitchMode);
}
/*
@@ -190,9 +195,9 @@ public class LambdaControlsConfig
*
* @return True if the HUD is enabled, else false.
*/
public boolean is_hud_enabled()
public boolean isHudEnabled()
{
return this.hud_enable;
return this.hudEnable;
}
/**
@@ -200,10 +205,10 @@ public class LambdaControlsConfig
*
* @param enable True if the HUD is enabled, else false.
*/
public void set_hud_enabled(boolean enable)
public void setHudEnabled(boolean enable)
{
this.hud_enable = enable;
this.config.set("hud.enable", this.hud_enable);
this.hudEnable = enable;
this.config.set("hud.enable", this.hudEnable);
}
/**
@@ -211,20 +216,20 @@ public class LambdaControlsConfig
*
* @return The HUD side.
*/
public @NotNull HudSide get_hud_side()
public @NotNull HudSide getHudSide()
{
return this.hud_side;
return this.hudSide;
}
/**
* Sets the HUD side in the configuration.
*
* @param hud_side The HUD side.
* @param hudSide The HUD side.
*/
public void set_hud_side(@NotNull HudSide hud_side)
public void setHudSide(@NotNull HudSide hudSide)
{
this.hud_side = hud_side;
this.config.set("hud.side", hud_side.get_name());
this.hudSide = hudSide;
this.config.set("hud.side", hudSide.getName());
}
/*
@@ -236,9 +241,9 @@ public class LambdaControlsConfig
*
* @return True if front block placing is enabled, else false.
*/
public boolean has_front_block_placing()
public boolean hasFrontBlockPlacing()
{
return this.config.getOrElse("gameplay.front_block_placing", DEFAULT_FRONT_BLOCK_PLACING);
return LambdaControlsFeature.FRONT_BLOCK_PLACING.isEnabled();
}
/**
@@ -246,8 +251,9 @@ public class LambdaControlsConfig
*
* @param enable True if front block placing is enabled, else false.
*/
public void set_front_block_placing(boolean enable)
public void setFrontBlockPlacing(boolean enable)
{
LambdaControlsFeature.FRONT_BLOCK_PLACING.setEnabled(enable);
this.config.set("gameplay.front_block_placing", enable);
}
@@ -256,19 +262,39 @@ public class LambdaControlsConfig
*
* @return True if fly drifting is enabled, else false.
*/
public boolean has_fly_drifting()
public boolean hasFlyDrifting()
{
return this.config.getOrElse("gameplay.fly_drifting", DEFAULT_FLY_DRIFTING);
return this.config.getOrElse("gameplay.fly.drifting", DEFAULT_FLY_DRIFTING);
}
/**
* Sets whether fly drifting is enabled or not.
*
* @param fly_drifting True if fly drifting is enabled, else false.
* @param flyDrifting True if fly drifting is enabled, else false.
*/
public void set_fly_drifting(boolean fly_drifting)
public void setFlyDrifting(boolean flyDrifting)
{
this.config.set("gameplay.fly_drifting", fly_drifting);
this.config.set("gameplay.fly.drifting", flyDrifting);
}
/**
* Returns whether vertical fly drifting is enabled or not.
*
* @return True if vertical fly drifting is enabled, else false.
*/
public boolean hasFlyVerticalDrifting()
{
return this.config.getOrElse("gameplay.fly.vertical_drifting", DEFAULT_FLY_VERTICAL_DRIFTING);
}
/**
* Sets whether vertical fly drifting is enabled or not.
*
* @param flyDrifting True if vertical fly drifting is enabled, else false.
*/
public void setFlyVerticalDrifting(boolean flyDrifting)
{
this.config.set("gameplay.fly.vertical_drifting", flyDrifting);
}
/*
@@ -280,15 +306,15 @@ public class LambdaControlsConfig
*
* @return The used controller.
*/
public @NotNull Controller get_controller()
public @NotNull Controller getController()
{
Object raw = this.config.getRaw("controller.id");
if (raw instanceof Number) {
return Controller.by_id((Integer) raw);
return Controller.byId((Integer) raw);
} else if (raw instanceof String) {
return Controller.by_guid((String) raw).orElse(Controller.by_id(GLFW.GLFW_JOYSTICK_1));
return Controller.byGuid((String) raw).orElse(Controller.byId(GLFW.GLFW_JOYSTICK_1));
}
return Controller.by_id(GLFW.GLFW_JOYSTICK_1);
return Controller.byId(GLFW.GLFW_JOYSTICK_1);
}
/**
@@ -296,9 +322,9 @@ public class LambdaControlsConfig
*
* @param controller The used controller.
*/
public void set_controller(@NotNull Controller controller)
public void setController(@NotNull Controller controller)
{
this.config.set("controller.id", controller.get_id());
this.config.set("controller.id", controller.getId());
}
/**
@@ -306,15 +332,15 @@ public class LambdaControlsConfig
*
* @return The second controller.
*/
public @NotNull Optional<Controller> get_second_controller()
public @NotNull Optional<Controller> getSecondController()
{
Object raw = this.config.getRaw("controller.id2");
if (raw instanceof Number) {
if ((int) raw == -1)
return Optional.empty();
return Optional.of(Controller.by_id((Integer) raw));
return Optional.of(Controller.byId((Integer) raw));
} else if (raw instanceof String) {
return Optional.of(Controller.by_guid((String) raw).orElse(Controller.by_id(GLFW.GLFW_JOYSTICK_1)));
return Optional.of(Controller.byGuid((String) raw).orElse(Controller.byId(GLFW.GLFW_JOYSTICK_1)));
}
return Optional.empty();
}
@@ -324,9 +350,9 @@ public class LambdaControlsConfig
*
* @param controller The second controller.
*/
public void set_second_controller(@Nullable Controller controller)
public void setSecondController(@Nullable Controller controller)
{
this.config.set("controller.id2", controller == null ? -1 : controller.get_id());
this.config.set("controller.id2", controller == null ? -1 : controller.getId());
}
/**
@@ -334,20 +360,20 @@ public class LambdaControlsConfig
*
* @return The controller's type.
*/
public @NotNull ControllerType get_controller_type()
public @NotNull ControllerType getControllerType()
{
return this.controller_type;
return this.controllerType;
}
/**
* Sets the controller's type.
*
* @param controller_type The controller's type.
* @param controllerType The controller's type.
*/
public void set_controller_type(@NotNull ControllerType controller_type)
public void setControllerType(@NotNull ControllerType controllerType)
{
this.controller_type = controller_type;
this.config.set("controller.type", controller_type.get_name());
this.controllerType = controllerType;
this.config.set("controller.type", controllerType.getName());
}
/**
@@ -355,19 +381,19 @@ public class LambdaControlsConfig
*
* @return The controller's dead zone value.
*/
public double get_dead_zone()
public double getDeadZone()
{
return this.dead_zone;
return this.deadZone;
}
/**
* Sets the controller's dead zone in the configuration.
*
* @param dead_zone The new controller's dead zone value.
* @param deadZone The new controller's dead zone value.
*/
public void set_dead_zone(double dead_zone)
public void setDeadZone(double deadZone)
{
this.dead_zone = dead_zone;
this.deadZone = deadZone;
}
/**
@@ -375,19 +401,19 @@ public class LambdaControlsConfig
*
* @return The rotation speed.
*/
public double get_rotation_speed()
public double getRotationSpeed()
{
return this.rotation_speed;
return this.rotationSpeed;
}
/**
* Sets the controller's rotation speed.
*
* @param rotation_speed The rotation speed.
* @param rotationSpeed The rotation speed.
*/
public void set_rotation_speed(double rotation_speed)
public void setRotationSpeed(double rotationSpeed)
{
this.rotation_speed = rotation_speed;
this.rotationSpeed = rotationSpeed;
}
/**
@@ -395,19 +421,19 @@ public class LambdaControlsConfig
*
* @return The mouse speed.
*/
public double get_mouse_speed()
public double getMouseSpeed()
{
return this.mouse_speed;
return this.mouseSpeed;
}
/**
* Sets the controller's mouse speed.
*
* @param mouse_speed The mouse speed.
* @param mouseSpeed The mouse speed.
*/
public void set_mouse_speed(double mouse_speed)
public void setMouseSpeed(double mouseSpeed)
{
this.mouse_speed = mouse_speed;
this.mouseSpeed = mouseSpeed;
}
/**
@@ -415,7 +441,7 @@ public class LambdaControlsConfig
*
* @return True if the right X axis is inverted, else false.
*/
public boolean does_invert_right_x_axis()
public boolean doesInvertRightXAxis()
{
return this.config.getOrElse("controller.invert_right_x_axis", false);
}
@@ -425,7 +451,7 @@ public class LambdaControlsConfig
*
* @param invert True if the right X axis is inverted, else false.
*/
public void set_invert_right_x_axis(boolean invert)
public void setInvertRightXAxis(boolean invert)
{
this.config.set("controller.invert_right_x_axis", invert);
}
@@ -435,7 +461,7 @@ public class LambdaControlsConfig
*
* @return True if the right Y axis is inverted, else false.
*/
public boolean does_invert_right_y_axis()
public boolean doesInvertRightYAxis()
{
return this.config.getOrElse("controller.invert_right_y_axis", false);
}
@@ -445,7 +471,7 @@ public class LambdaControlsConfig
*
* @param invert True if the right Y axis is inverted, else false.
*/
public void set_invert_right_y_axis(boolean invert)
public void setInvertRightYAxis(boolean invert)
{
this.config.set("controller.invert_right_y_axis", invert);
}
@@ -455,19 +481,19 @@ public class LambdaControlsConfig
*
* @return True if unfocused controller input is allowed, else false.
*/
public boolean has_unfocused_input()
public boolean hasUnfocusedInput()
{
return this.unfocused_input;
return this.unfocusedInput;
}
/**
* Sets whether unfocused controller input is allowed or not.
*
* @param unfocused_input True if unfocused controller input is allowed, else false.
* @param unfocusedInput True if unfocused controller input is allowed, else false.
*/
public void set_unfocused_input(boolean unfocused_input)
public void setUnfocusedInput(boolean unfocusedInput)
{
this.unfocused_input = unfocused_input;
this.unfocusedInput = unfocusedInput;
}
/**
@@ -475,9 +501,9 @@ public class LambdaControlsConfig
*
* @return The right X axis sign.
*/
public double get_right_x_axis_sign()
public double getRightXAxisSign()
{
return this.does_invert_right_x_axis() ? -1.0 : 1.0;
return this.doesInvertRightXAxis() ? -1.0 : 1.0;
}
/**
@@ -485,9 +511,9 @@ public class LambdaControlsConfig
*
* @return The right Y axis sign.
*/
public double get_right_y_axis_sign()
public double getRightYAxisSign()
{
return this.does_invert_right_y_axis() ? -1.0 : 1.0;
return this.doesInvertRightYAxis() ? -1.0 : 1.0;
}
/**
@@ -495,12 +521,12 @@ public class LambdaControlsConfig
*
* @param button The button binding.
*/
public void load_button_binding(@NotNull ButtonBinding button)
public void loadButtonBinding(@NotNull ButtonBinding button)
{
button.set_button(button.get_default_button());
String button_code = this.config.getOrElse("controller.controls." + button.get_name(), button.get_button_code());
button.setButton(button.getDefaultButton());
String code = this.config.getOrElse("controller.controls." + button.getName(), button.getButtonCode());
Matcher matcher = BUTTON_BINDING_PATTERN.matcher(button_code);
Matcher matcher = BUTTON_BINDING_PATTERN.matcher(code);
try {
int[] buttons = new int[1];
@@ -510,27 +536,27 @@ public class LambdaControlsConfig
if (count > buttons.length)
buttons = Arrays.copyOf(buttons, count);
String current;
if (!this.check_validity(button, button_code, current = matcher.group(1)))
if (!this.checkValidity(button, code, current = matcher.group(1)))
return;
buttons[count - 1] = Integer.parseInt(current);
}
if (count == 0) {
this.mod.warn("Malformed config value \"" + button_code + "\" for binding \"" + button.get_name() + "\".");
this.set_button_binding(button, new int[]{-1});
this.mod.warn("Malformed config value \"" + code + "\" for binding \"" + button.getName() + "\".");
this.setButtonBinding(button, new int[]{-1});
}
button.set_button(buttons);
button.setButton(buttons);
} catch (Exception e) {
this.mod.warn("Malformed config value \"" + button_code + "\" for binding \"" + button.get_name() + "\".");
this.config.set("controller.controls." + button.get_name(), button.get_button_code());
this.mod.warn("Malformed config value \"" + code + "\" for binding \"" + button.getName() + "\".");
this.config.set("controller.controls." + button.getName(), button.getButtonCode());
}
}
private boolean check_validity(@NotNull ButtonBinding binding, @NotNull String input, String group)
private boolean checkValidity(@NotNull ButtonBinding binding, @NotNull String input, String group)
{
if (group == null) {
this.mod.warn("Malformed config value \"" + input + "\" for binding \"" + binding.get_name() + "\".");
this.config.set("controller.controls." + binding.get_name(), binding.get_button_code());
this.mod.warn("Malformed config value \"" + input + "\" for binding \"" + binding.getName() + "\".");
this.config.set("controller.controls." + binding.getName(), binding.getButtonCode());
return false;
}
return true;
@@ -542,38 +568,38 @@ public class LambdaControlsConfig
* @param binding The button binding.
* @param button The button.
*/
public void set_button_binding(@NotNull ButtonBinding binding, int[] button)
public void setButtonBinding(@NotNull ButtonBinding binding, int[] button)
{
binding.set_button(button);
this.config.set("controller.controls." + binding.get_name(), binding.get_button_code());
binding.setButton(button);
this.config.set("controller.controls." + binding.getName(), binding.getButtonCode());
}
public boolean is_back_button(int btn, boolean is_btn, int state)
public boolean isBackButton(int btn, boolean isBtn, int state)
{
if (!is_btn && state == 0)
if (!isBtn && state == 0)
return false;
return ButtonBinding.axis_as_button(GLFW_GAMEPAD_AXIS_LEFT_Y, false) == ButtonBinding.axis_as_button(btn, state == 1);
return ButtonBinding.axisAsButton(GLFW_GAMEPAD_AXIS_LEFT_Y, false) == ButtonBinding.axisAsButton(btn, state == 1);
}
public boolean is_forward_button(int btn, boolean is_btn, int state)
public boolean isForwardButton(int btn, boolean isBtn, int state)
{
if (!is_btn && state == 0)
if (!isBtn && state == 0)
return false;
return ButtonBinding.axis_as_button(GLFW_GAMEPAD_AXIS_LEFT_Y, true) == ButtonBinding.axis_as_button(btn, state == 1);
return ButtonBinding.axisAsButton(GLFW_GAMEPAD_AXIS_LEFT_Y, true) == ButtonBinding.axisAsButton(btn, state == 1);
}
public boolean is_left_button(int btn, boolean is_btn, int state)
public boolean isLeftButton(int btn, boolean isBtn, int state)
{
if (!is_btn && state == 0)
if (!isBtn && state == 0)
return false;
return ButtonBinding.axis_as_button(GLFW_GAMEPAD_AXIS_LEFT_X, false) == ButtonBinding.axis_as_button(btn, state == 1);
return ButtonBinding.axisAsButton(GLFW_GAMEPAD_AXIS_LEFT_X, false) == ButtonBinding.axisAsButton(btn, state == 1);
}
public boolean is_right_button(int btn, boolean is_btn, int state)
public boolean isRightButton(int btn, boolean isBtn, int state)
{
if (!is_btn && state == 0)
if (!isBtn && state == 0)
return false;
return ButtonBinding.axis_as_button(GLFW_GAMEPAD_AXIS_LEFT_X, true) == ButtonBinding.axis_as_button(btn, state == 1);
return ButtonBinding.axisAsButton(GLFW_GAMEPAD_AXIS_LEFT_X, true) == ButtonBinding.axisAsButton(btn, state == 1);
}
/**
@@ -582,7 +608,7 @@ public class LambdaControlsConfig
* @param axis The axis index.
* @return True if the axis is used for movements, else false.
*/
public boolean is_movement_axis(int axis)
public boolean isMovementAxis(int axis)
{
return axis == GLFW_GAMEPAD_AXIS_LEFT_Y || axis == GLFW_GAMEPAD_AXIS_LEFT_X;
}

View File

@@ -12,18 +12,19 @@ package me.lambdaurora.lambdacontrols.client;
import me.lambdaurora.lambdacontrols.client.controller.ButtonBinding;
import me.lambdaurora.lambdacontrols.client.controller.Controller;
import me.lambdaurora.lambdacontrols.client.controller.InputManager;
import me.lambdaurora.lambdacontrols.client.gui.LambdaControlsControlsScreen;
import me.lambdaurora.lambdacontrols.client.gui.ControllerControlsScreen;
import me.lambdaurora.lambdacontrols.client.gui.TouchscreenOverlay;
import me.lambdaurora.lambdacontrols.client.mixin.CreativeInventoryScreenAccessor;
import me.lambdaurora.lambdacontrols.client.mixin.EntryListWidgetAccessor;
import me.lambdaurora.lambdacontrols.client.util.AbstractContainerScreenAccessor;
import me.lambdaurora.lambdacontrols.client.util.MouseAccessor;
import me.lambdaurora.lambdacontrols.client.util.ContainerScreenAccessor;
import me.lambdaurora.spruceui.SpruceLabelWidget;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.Element;
import net.minecraft.client.gui.ParentElement;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.screen.advancement.AdvancementsScreen;
import net.minecraft.client.gui.screen.ingame.AbstractContainerScreen;
import net.minecraft.client.gui.screen.ingame.ContainerScreen;
import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen;
import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen;
import net.minecraft.client.gui.screen.multiplayer.MultiplayerServerListWidget;
import net.minecraft.client.gui.screen.world.WorldListWidget;
@@ -46,7 +47,8 @@ import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import static me.lambdaurora.lambdacontrols.client.controller.ButtonBinding.axis_as_button;
import static me.lambdaurora.lambdacontrols.client.controller.ButtonBinding.axisAsButton;
import static me.lambdaurora.lambdacontrols.client.controller.InputManager.INPUT_MANAGER;
import static org.lwjgl.glfw.GLFW.*;
/**
@@ -58,24 +60,22 @@ import static org.lwjgl.glfw.GLFW.*;
*/
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;
// Cooldowns
private int action_gui_cooldown = 0;
private int ignore_next_a = 0;
private int actionGuiCooldown = 0;
private int ignoreNextA = 0;
// Sneak state.
private double prev_target_yaw = 0.0;
private double prev_target_pitch = 0.0;
private double target_yaw = 0.0;
private double target_pitch = 0.0;
private float prev_x_axis = 0.F;
private float prev_y_axis = 0.F;
private int prev_target_mouse_x = 0;
private int prev_target_mouse_y = 0;
private int target_mouse_x = 0;
private int target_mouse_y = 0;
private float mouse_speed_x = 0.F;
private float mouse_speed_y = 0.F;
private double prevTargetYaw = 0.0;
private double prevTargetPitch = 0.0;
private double targetYaw = 0.0;
private double targetPitch = 0.0;
private float prevXAxis = 0.F;
private float prevYAxis = 0.F;
private int targetMouseX = 0;
private int targetMouseY = 0;
private float mouseSpeedX = 0.F;
private float mouseSpeedY = 0.F;
public LambdaInput(@NotNull LambdaControlsClient mod)
{
@@ -87,22 +87,24 @@ public class LambdaInput
*
* @param client The client instance.
*/
public void on_tick(@NotNull MinecraftClient client)
public void onTick(@NotNull MinecraftClient client)
{
this.prev_target_yaw = this.target_yaw;
this.prev_target_pitch = this.target_pitch;
this.prevTargetYaw = this.targetYaw;
this.prevTargetPitch = this.targetPitch;
// Handles the key bindings.
if (LambdaControlsClient.BINDING_LOOK_UP.isPressed()) {
this.handle_look(client, GLFW_GAMEPAD_AXIS_RIGHT_Y, 0.8F, 2);
this.handleLook(client, GLFW_GAMEPAD_AXIS_RIGHT_Y, 0.8F, 2);
} else if (LambdaControlsClient.BINDING_LOOK_DOWN.isPressed()) {
this.handle_look(client, GLFW_GAMEPAD_AXIS_RIGHT_Y, 0.8F, 1);
this.handleLook(client, GLFW_GAMEPAD_AXIS_RIGHT_Y, 0.8F, 1);
}
if (LambdaControlsClient.BINDING_LOOK_LEFT.isPressed()) {
this.handle_look(client, GLFW_GAMEPAD_AXIS_RIGHT_X, 0.8F, 2);
this.handleLook(client, GLFW_GAMEPAD_AXIS_RIGHT_X, 0.8F, 2);
} else if (LambdaControlsClient.BINDING_LOOK_RIGHT.isPressed()) {
this.handle_look(client, GLFW_GAMEPAD_AXIS_RIGHT_X, 0.8F, 1);
this.handleLook(client, GLFW_GAMEPAD_AXIS_RIGHT_X, 0.8F, 1);
}
INPUT_MANAGER.tick(client);
}
/**
@@ -110,49 +112,47 @@ public class LambdaInput
*
* @param client The client instance.
*/
public void on_controller_tick(@NotNull MinecraftClient client)
public void onControllerTick(@NotNull MinecraftClient client)
{
BUTTON_COOLDOWNS.entrySet().stream().filter(entry -> entry.getValue() > 0).forEach(entry -> BUTTON_COOLDOWNS.put(entry.getKey(), entry.getValue() - 1));
// Decreases the cooldown for GUI actions.
if (this.action_gui_cooldown > 0)
--this.action_gui_cooldown;
this.prev_target_mouse_x = this.target_mouse_x;
this.prev_target_mouse_y = this.target_mouse_y;
if (this.actionGuiCooldown > 0)
--this.actionGuiCooldown;
InputManager.update_states();
InputManager.updateStates();
Controller controller = this.config.get_controller();
if (controller.is_connected()) {
GLFWGamepadState state = controller.get_state();
this.fetch_button_input(client, state, false);
this.fetch_axe_input(client, state, false);
Controller controller = this.config.getController();
if (controller.isConnected()) {
GLFWGamepadState state = controller.getState();
this.fetchButtonInput(client, state, false);
this.fetchAxeInput(client, state, false);
}
this.config.get_second_controller().filter(Controller::is_connected)
this.config.getSecondController().filter(Controller::isConnected)
.ifPresent(joycon -> {
GLFWGamepadState state = joycon.get_state();
this.fetch_button_input(client, state, true);
this.fetch_axe_input(client, state, true);
GLFWGamepadState state = joycon.getState();
this.fetchButtonInput(client, state, true);
this.fetchAxeInput(client, state, true);
});
boolean allow_input = true;
boolean allowInput = true;
if (client.currentScreen instanceof LambdaControlsControlsScreen && ((LambdaControlsControlsScreen) client.currentScreen).focused_binding != null)
allow_input = false;
if (client.currentScreen instanceof ControllerControlsScreen && ((ControllerControlsScreen) client.currentScreen).focusedBinding != null)
allowInput = false;
if (allow_input)
InputManager.update_bindings(client);
if (allowInput)
InputManager.updateBindings(client);
if (this.ignore_next_a > 0)
this.ignore_next_a--;
if (this.ignoreNextA > 0)
this.ignoreNextA--;
if (client.currentScreen instanceof LambdaControlsControlsScreen && InputManager.STATES.entrySet().parallelStream().map(Map.Entry::getValue).allMatch(ButtonState::is_unpressed)) {
LambdaControlsControlsScreen controls_screen = (LambdaControlsControlsScreen) client.currentScreen;
if (controls_screen.focused_binding != null && !controls_screen.waiting) {
int[] buttons = new int[controls_screen.current_buttons.size()];
for (int i = 0; i < controls_screen.current_buttons.size(); i++)
buttons[i] = controls_screen.current_buttons.get(i);
controls_screen.focused_binding.set_button(buttons);
controls_screen.focused_binding = null;
if (client.currentScreen instanceof ControllerControlsScreen && InputManager.STATES.entrySet().parallelStream().map(Map.Entry::getValue).allMatch(ButtonState::isUnpressed)) {
ControllerControlsScreen screen = (ControllerControlsScreen) client.currentScreen;
if (screen.focusedBinding != null && !screen.waiting) {
int[] buttons = new int[screen.currentButtons.size()];
for (int i = 0; i < screen.currentButtons.size(); i++)
buttons[i] = screen.currentButtons.get(i);
screen.focusedBinding.setButton(buttons);
screen.focusedBinding = null;
}
}
}
@@ -163,15 +163,10 @@ public class LambdaInput
* @param client The client instance.
* @param screen The screen to render.
*/
public void on_pre_render_screen(@NotNull MinecraftClient client, @NotNull Screen screen)
public void onPreRenderScreen(@NotNull MinecraftClient client, @NotNull Screen screen)
{
if (!is_screen_interactive(screen)) {
if (this.prev_target_mouse_x != this.target_mouse_x || this.prev_target_mouse_y != this.target_mouse_y) {
double mouse_x = this.prev_target_mouse_x + (this.target_mouse_x - this.prev_target_mouse_x) * client.getTickDelta() + 0.5;
double mouse_y = this.prev_target_mouse_y + (this.target_mouse_y - this.prev_target_mouse_y) * client.getTickDelta() + 0.5;
GLFW.glfwSetCursorPos(client.getWindow().getHandle(), mouse_x, mouse_y);
((MouseAccessor) client.mouse).lambdacontrols_on_cursor_pos(client.getWindow().getHandle(), mouse_x, mouse_y);
}
if (!isScreenInteractive(screen)) {
INPUT_MANAGER.updateMousePosition(client);
}
}
@@ -180,113 +175,112 @@ public class LambdaInput
*
* @param client The client instance.
*/
public void on_render(@NotNull MinecraftClient client)
public void onRender(@NotNull MinecraftClient client)
{
if ((client.currentScreen == null || client.currentScreen instanceof TouchscreenOverlay) &&
(this.prev_target_yaw != this.target_yaw || this.prev_target_pitch != this.target_pitch)) {
float delta_yaw = (float) ((this.target_yaw - client.player.prevYaw) * client.getTickDelta());
float delta_pitch = (float) ((this.target_pitch - client.player.prevPitch) * client.getTickDelta());
float rotation_yaw = client.player.prevYaw + delta_yaw;
float rotation_pitch = client.player.prevPitch + delta_pitch;
client.player.yaw = rotation_yaw;
client.player.pitch = MathHelper.clamp(rotation_pitch, -90.F, 90.F);
(this.prevTargetYaw != this.targetYaw || this.prevTargetPitch != this.targetPitch)) {
float deltaYaw = (float) ((this.targetYaw - client.player.prevYaw) * client.getTickDelta());
float deltaPitch = (float) ((this.targetPitch - client.player.prevPitch) * client.getTickDelta());
float rotationYaw = client.player.prevYaw + deltaYaw;
float rotationPitch = client.player.prevPitch + deltaPitch;
client.player.yaw = rotationYaw;
client.player.pitch = MathHelper.clamp(rotationPitch, -90.F, 90.F);
if (client.player.isRiding()) {
client.player.getVehicle().copyPositionAndRotation(client.player);
}
client.getTutorialManager().onUpdateMouse(delta_pitch, delta_yaw);
client.getTutorialManager().onUpdateMouse(deltaPitch, deltaYaw);
}
}
/**
* This method is called when a Screen is opened.
*
* @param client The client instance.
* @param window_width The window width.
* @param window_height The window height.
* @param client The client instance.
* @param windowWidth The window width.
* @param windowHeight The window height.
*/
public void on_screen_open(@NotNull MinecraftClient client, int window_width, int window_height)
public void onScreenOpen(@NotNull MinecraftClient client, int windowWidth, int windowHeight)
{
if (client.currentScreen == null) {
this.mouse_speed_x = this.mouse_speed_y = 0.0F;
this.target_mouse_x = this.prev_target_mouse_x = (int) (window_width / 2.F);
this.target_mouse_y = this.prev_target_mouse_y = (int) (window_height / 2.F);
this.mouseSpeedX = this.mouseSpeedY = 0.0F;
INPUT_MANAGER.resetMousePosition(windowWidth, windowHeight);
}
}
private void fetch_button_input(@NotNull MinecraftClient client, @NotNull GLFWGamepadState gamepad_state, boolean left_joycon)
private void fetchButtonInput(@NotNull MinecraftClient client, @NotNull GLFWGamepadState gamepadState, boolean leftJoycon)
{
ByteBuffer buffer = gamepad_state.buttons();
ByteBuffer buffer = gamepadState.buttons();
for (int i = 0; i < buffer.limit(); i++) {
int btn = left_joycon ? ButtonBinding.controller2_button(i) : i;
boolean btn_state = buffer.get() == (byte) 1;
ButtonState current_state = ButtonState.NONE;
ButtonState previous_state = InputManager.STATES.getOrDefault(btn, ButtonState.NONE);
int btn = leftJoycon ? ButtonBinding.controller2Button(i) : i;
boolean btnState = buffer.get() == (byte) 1;
ButtonState state = ButtonState.NONE;
ButtonState previousState = InputManager.STATES.getOrDefault(btn, ButtonState.NONE);
if (btn_state != previous_state.is_pressed()) {
current_state = btn_state ? ButtonState.PRESS : ButtonState.RELEASE;
this.handle_button(client, btn, btn_state ? 0 : 1, btn_state);
if (btn_state)
if (btnState != previousState.isPressed()) {
state = btnState ? ButtonState.PRESS : ButtonState.RELEASE;
this.handleButton(client, btn, btnState ? 0 : 1, btnState);
if (btnState)
BUTTON_COOLDOWNS.put(btn, 5);
} else if (btn_state) {
current_state = ButtonState.REPEAT;
} else if (btnState) {
state = ButtonState.REPEAT;
if (BUTTON_COOLDOWNS.getOrDefault(btn, 0) == 0) {
BUTTON_COOLDOWNS.put(btn, 5);
this.handle_button(client, btn, 2, true);
this.handleButton(client, btn, 2, true);
}
}
InputManager.STATES.put(btn, current_state);
InputManager.STATES.put(btn, state);
}
}
private void fetch_axe_input(@NotNull MinecraftClient client, @NotNull GLFWGamepadState gamepad_state, boolean left_joycon)
private void fetchAxeInput(@NotNull MinecraftClient client, @NotNull GLFWGamepadState gamepadState, boolean leftJoycon)
{
FloatBuffer buffer = gamepad_state.axes();
FloatBuffer buffer = gamepadState.axes();
for (int i = 0; i < buffer.limit(); i++) {
int axis = left_joycon ? ButtonBinding.controller2_button(i) : i;
int axis = leftJoycon ? ButtonBinding.controller2Button(i) : i;
float value = buffer.get();
float abs_value = Math.abs(value);
float absValue = Math.abs(value);
if (i == GLFW.GLFW_GAMEPAD_AXIS_LEFT_Y)
value *= -1.0F;
int state = value > this.config.get_dead_zone() ? 1 : (value < -this.config.get_dead_zone() ? 2 : 0);
this.handle_axe(client, axis, value, abs_value, state);
int state = value > this.config.getDeadZone() ? 1 : (value < -this.config.getDeadZone() ? 2 : 0);
this.handleAxe(client, axis, value, absValue, state);
}
}
private void handle_button(@NotNull MinecraftClient client, int button, int action, boolean state)
private void handleButton(@NotNull MinecraftClient client, int button, int action, boolean state)
{
if (client.currentScreen instanceof LambdaControlsControlsScreen) {
LambdaControlsControlsScreen controls_screen = (LambdaControlsControlsScreen) client.currentScreen;
if (controls_screen.focused_binding != null) {
if (action == 0 && !controls_screen.current_buttons.contains(button)) {
controls_screen.current_buttons.add(button);
if (client.currentScreen instanceof ControllerControlsScreen) {
ControllerControlsScreen screen = (ControllerControlsScreen) client.currentScreen;
if (screen.focusedBinding != null) {
if (action == 0 && !screen.currentButtons.contains(button)) {
screen.currentButtons.add(button);
int[] buttons = new int[controls_screen.current_buttons.size()];
for (int i = 0; i < controls_screen.current_buttons.size(); i++)
buttons[i] = controls_screen.current_buttons.get(i);
controls_screen.focused_binding.set_button(buttons);
int[] buttons = new int[screen.currentButtons.size()];
for (int i = 0; i < screen.currentButtons.size(); i++)
buttons[i] = screen.currentButtons.get(i);
screen.focusedBinding.setButton(buttons);
controls_screen.waiting = false;
screen.waiting = false;
}
return;
}
}
if (action == 0 || action == 2) {
if (client.currentScreen != null && is_screen_interactive(client.currentScreen)
if (client.currentScreen != null && isScreenInteractive(client.currentScreen)
&& (button == GLFW.GLFW_GAMEPAD_BUTTON_DPAD_UP || button == GLFW.GLFW_GAMEPAD_BUTTON_DPAD_DOWN
|| button == GLFW.GLFW_GAMEPAD_BUTTON_DPAD_LEFT || button == GLFW.GLFW_GAMEPAD_BUTTON_DPAD_RIGHT)) {
if (this.action_gui_cooldown == 0) {
if (this.actionGuiCooldown == 0) {
if (button == GLFW.GLFW_GAMEPAD_BUTTON_DPAD_UP) {
this.change_focus(client.currentScreen, false);
this.changeFocus(client.currentScreen, false);
} else if (button == GLFW.GLFW_GAMEPAD_BUTTON_DPAD_DOWN) {
this.change_focus(client.currentScreen, true);
this.changeFocus(client.currentScreen, true);
} else if (button == GLFW.GLFW_GAMEPAD_BUTTON_DPAD_LEFT) {
this.handle_left_right(client.currentScreen, false);
this.handleLeftRight(client.currentScreen, false);
} else {
this.handle_left_right(client.currentScreen, true);
this.handleLeftRight(client.currentScreen, true);
}
}
return;
@@ -295,33 +289,38 @@ public class LambdaInput
if (action == 1) {
if (button == GLFW.GLFW_GAMEPAD_BUTTON_A && client.currentScreen != null) {
if (this.action_gui_cooldown == 0) {
if (this.actionGuiCooldown == 0) {
Element focused = client.currentScreen.getFocused();
if (focused != null && is_screen_interactive(client.currentScreen)) {
if (this.handle_a_button(client.currentScreen, focused)) {
this.action_gui_cooldown = 5; // Prevent to press too quickly the focused element, so we have to skip 5 ticks.
if (focused != null && isScreenInteractive(client.currentScreen)) {
if (this.handleAButton(client.currentScreen, focused)) {
this.actionGuiCooldown = 5; // Prevent to press too quickly the focused element, so we have to skip 5 ticks.
return;
}
}
}
}
if (client.currentScreen instanceof AbstractContainerScreen && client.interactionManager != null && client.player != null) {
double pos_x = client.mouse.getX() * (double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth();
double pos_y = client.mouse.getY() * (double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight();
Slot slot = ((AbstractContainerScreenAccessor) client.currentScreen).lambdacontrols_get_slot_at(pos_x, pos_y);
if (client.currentScreen instanceof ContainerScreen && client.interactionManager != null && client.player != null) {
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();
Slot slot = ((ContainerScreenAccessor) client.currentScreen).lambdacontrols_getSlotAt(x, y);
SlotActionType slotAction = SlotActionType.PICKUP;
if (button == GLFW.GLFW_GAMEPAD_BUTTON_A && slot != null) {
client.interactionManager.clickSlot(((AbstractContainerScreen) client.currentScreen).getContainer().syncId, slot.id, GLFW.GLFW_MOUSE_BUTTON_1, SlotActionType.PICKUP, client.player);
this.action_gui_cooldown = 5;
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(((AbstractContainerScreen) client.currentScreen).getContainer().syncId, slot.id, GLFW.GLFW_MOUSE_BUTTON_2, SlotActionType.PICKUP, client.player);
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(((AbstractContainerScreen) client.currentScreen).getContainer().syncId, slot.id, GLFW.GLFW_MOUSE_BUTTON_1, SlotActionType.QUICK_MOVE, client.player);
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) {
@@ -332,158 +331,152 @@ public class LambdaInput
}
}
if (button == GLFW.GLFW_GAMEPAD_BUTTON_A && client.currentScreen != null && !is_screen_interactive(client.currentScreen) && this.action_gui_cooldown == 0 && this.ignore_next_a == 0) {
double mouse_x = client.mouse.getX() * (double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth();
double mouse_y = client.mouse.getY() * (double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight();
if (button == GLFW.GLFW_GAMEPAD_BUTTON_A && client.currentScreen != null && !isScreenInteractive(client.currentScreen) && this.actionGuiCooldown == 0 && this.ignoreNextA == 0) {
double mouseX = client.mouse.getX() * (double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth();
double mouseY = client.mouse.getY() * (double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight();
if (action == 0) {
client.currentScreen.mouseClicked(mouse_x, mouse_y, GLFW.GLFW_MOUSE_BUTTON_1);
client.currentScreen.mouseClicked(mouseX, mouseY, GLFW.GLFW_MOUSE_BUTTON_1);
} else if (action == 1) {
client.currentScreen.mouseReleased(mouse_x, mouse_y, GLFW.GLFW_MOUSE_BUTTON_1);
client.currentScreen.mouseReleased(mouseX, mouseY, GLFW.GLFW_MOUSE_BUTTON_1);
}
this.action_gui_cooldown = 5;
this.actionGuiCooldown = 5;
}
}
private void handle_axe(@NotNull MinecraftClient client, int axis, float value, float abs_value, int state)
private void handleAxe(@NotNull MinecraftClient client, int axis, float value, float absValue, int state)
{
int as_button_state = value > 0.5F ? 1 : (value < -0.5F ? 2 : 0);
int asButtonState = value > 0.5F ? 1 : (value < -0.5F ? 2 : 0);
if (axis == GLFW_GAMEPAD_AXIS_LEFT_TRIGGER || axis == GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER || axis == ButtonBinding.controller2_button(GLFW.GLFW_GAMEPAD_AXIS_LEFT_TRIGGER) ||
axis == ButtonBinding.controller2_button(GLFW.GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER))
if (as_button_state == 2)
as_button_state = 0;
if (axis == GLFW_GAMEPAD_AXIS_LEFT_TRIGGER || axis == GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER || axis == ButtonBinding.controller2Button(GLFW.GLFW_GAMEPAD_AXIS_LEFT_TRIGGER) ||
axis == ButtonBinding.controller2Button(GLFW.GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER))
if (asButtonState == 2)
asButtonState = 0;
{
boolean current_plus_state = as_button_state == 1;
boolean current_minus_state = as_button_state == 2;
ButtonState previous_plus_state = InputManager.STATES.getOrDefault(axis_as_button(axis, true), ButtonState.NONE);
ButtonState previous_minus_state = InputManager.STATES.getOrDefault(axis_as_button(axis, false), ButtonState.NONE);
boolean currentPlusState = asButtonState == 1;
boolean currentMinusState = asButtonState == 2;
ButtonState previousPlusState = InputManager.STATES.getOrDefault(axisAsButton(axis, true), ButtonState.NONE);
ButtonState previousMinusState = InputManager.STATES.getOrDefault(axisAsButton(axis, false), ButtonState.NONE);
if (current_plus_state != previous_plus_state.is_pressed()) {
InputManager.STATES.put(axis_as_button(axis, true), current_plus_state ? ButtonState.PRESS : ButtonState.RELEASE);
if (current_plus_state)
BUTTON_COOLDOWNS.put(axis_as_button(axis, true), 5);
} else if (current_plus_state) {
InputManager.STATES.put(axis_as_button(axis, true), ButtonState.REPEAT);
if (BUTTON_COOLDOWNS.getOrDefault(axis_as_button(axis, true), 0) == 0) {
BUTTON_COOLDOWNS.put(axis_as_button(axis, true), 5);
if (currentPlusState != previousPlusState.isPressed()) {
InputManager.STATES.put(axisAsButton(axis, true), currentPlusState ? ButtonState.PRESS : ButtonState.RELEASE);
if (currentPlusState)
BUTTON_COOLDOWNS.put(axisAsButton(axis, true), 5);
} else if (currentPlusState) {
InputManager.STATES.put(axisAsButton(axis, true), ButtonState.REPEAT);
if (BUTTON_COOLDOWNS.getOrDefault(axisAsButton(axis, true), 0) == 0) {
BUTTON_COOLDOWNS.put(axisAsButton(axis, true), 5);
}
}
if (current_minus_state != previous_minus_state.is_pressed()) {
InputManager.STATES.put(axis_as_button(axis, false), current_minus_state ? ButtonState.PRESS : ButtonState.RELEASE);
if (current_minus_state)
BUTTON_COOLDOWNS.put(axis_as_button(axis, false), 5);
} else if (current_minus_state) {
InputManager.STATES.put(axis_as_button(axis, false), ButtonState.REPEAT);
if (BUTTON_COOLDOWNS.getOrDefault(axis_as_button(axis, false), 0) == 0) {
BUTTON_COOLDOWNS.put(axis_as_button(axis, false), 5);
if (currentMinusState != previousMinusState.isPressed()) {
InputManager.STATES.put(axisAsButton(axis, false), currentMinusState ? ButtonState.PRESS : ButtonState.RELEASE);
if (currentMinusState)
BUTTON_COOLDOWNS.put(axisAsButton(axis, false), 5);
} else if (currentMinusState) {
InputManager.STATES.put(axisAsButton(axis, false), ButtonState.REPEAT);
if (BUTTON_COOLDOWNS.getOrDefault(axisAsButton(axis, false), 0) == 0) {
BUTTON_COOLDOWNS.put(axisAsButton(axis, false), 5);
}
}
}
if (client.currentScreen instanceof LambdaControlsControlsScreen) {
LambdaControlsControlsScreen controls_screen = (LambdaControlsControlsScreen) client.currentScreen;
if (controls_screen.focused_binding != null) {
if (as_button_state != 0 && !controls_screen.current_buttons.contains(axis_as_button(axis, as_button_state == 1))) {
if (client.currentScreen instanceof ControllerControlsScreen) {
ControllerControlsScreen screen = (ControllerControlsScreen) client.currentScreen;
if (screen.focusedBinding != null) {
if (asButtonState != 0 && !screen.currentButtons.contains(axisAsButton(axis, asButtonState == 1))) {
controls_screen.current_buttons.add(axis_as_button(axis, as_button_state == 1));
screen.currentButtons.add(axisAsButton(axis, asButtonState == 1));
int[] buttons = new int[controls_screen.current_buttons.size()];
for (int i = 0; i < controls_screen.current_buttons.size(); i++)
buttons[i] = controls_screen.current_buttons.get(i);
controls_screen.focused_binding.set_button(buttons);
int[] buttons = new int[screen.currentButtons.size()];
for (int i = 0; i < screen.currentButtons.size(); i++)
buttons[i] = screen.currentButtons.get(i);
screen.focusedBinding.setButton(buttons);
controls_screen.waiting = false;
screen.waiting = false;
}
return;
}
}
double dead_zone = this.config.get_dead_zone();
double deadZone = this.config.getDeadZone();
if (client.currentScreen == null) {
// Handles the look direction.
this.handle_look(client, axis, (float) (abs_value / (1.0 - this.config.get_dead_zone())), state);
this.handleLook(client, axis, (float) (absValue / (1.0 - this.config.getDeadZone())), state);
} else {
boolean allow_mouse_control = true;
boolean allowMouseControl = true;
if (this.action_gui_cooldown == 0 && this.config.is_movement_axis(axis) && is_screen_interactive(client.currentScreen)) {
if (this.config.is_forward_button(axis, false, as_button_state)) {
allow_mouse_control = this.change_focus(client.currentScreen, false);
} else if (this.config.is_back_button(axis, false, as_button_state)) {
allow_mouse_control = this.change_focus(client.currentScreen, true);
} else if (this.config.is_left_button(axis, false, as_button_state)) {
allow_mouse_control = this.handle_left_right(client.currentScreen, false);
} else if (this.config.is_right_button(axis, false, as_button_state)) {
allow_mouse_control = this.handle_left_right(client.currentScreen, true);
if (this.actionGuiCooldown == 0 && this.config.isMovementAxis(axis) && isScreenInteractive(client.currentScreen)) {
if (this.config.isForwardButton(axis, false, asButtonState)) {
allowMouseControl = this.changeFocus(client.currentScreen, false);
} else if (this.config.isBackButton(axis, false, asButtonState)) {
allowMouseControl = this.changeFocus(client.currentScreen, true);
} else if (this.config.isLeftButton(axis, false, asButtonState)) {
allowMouseControl = this.handleLeftRight(client.currentScreen, false);
} else if (this.config.isRightButton(axis, false, asButtonState)) {
allowMouseControl = this.handleLeftRight(client.currentScreen, true);
}
}
float movement_x = 0.0F;
float movement_y = 0.0F;
float movementX = 0.0F;
float movementY = 0.0F;
if (this.config.is_back_button(axis, false, (value > 0 ? 1 : 2))) {
movement_y = abs_value;
} else if (this.config.is_forward_button(axis, false, (value > 0 ? 1 : 2))) {
movement_y = -abs_value;
} else if (this.config.is_left_button(axis, false, (value > 0 ? 1 : 2))) {
movement_x = -abs_value;
} else if (this.config.is_right_button(axis, false, (value > 0 ? 1 : 2))) {
movement_x = abs_value;
if (this.config.isBackButton(axis, false, (value > 0 ? 1 : 2))) {
movementY = absValue;
} else if (this.config.isForwardButton(axis, false, (value > 0 ? 1 : 2))) {
movementY = -absValue;
} else if (this.config.isLeftButton(axis, false, (value > 0 ? 1 : 2))) {
movementX = -absValue;
} else if (this.config.isRightButton(axis, false, (value > 0 ? 1 : 2))) {
movementX = absValue;
}
if (client.currentScreen != null && allow_mouse_control) {
boolean moving = Math.abs(movement_y) >= dead_zone || Math.abs(movement_x) >= dead_zone;
if (client.currentScreen != null && allowMouseControl) {
boolean moving = Math.abs(movementY) >= deadZone || Math.abs(movementX) >= deadZone;
if (moving) {
/*
Updates the target mouse position when the initial movement stick movement is detected.
It prevents the cursor to jump to the old target mouse position if the user moves the cursor with the mouse.
*/
if (Math.abs(prev_x_axis) < dead_zone && Math.abs(prev_y_axis) < dead_zone) {
double mouse_x = client.mouse.getX();
double mouse_y = client.mouse.getY();
this.prev_target_mouse_x = this.target_mouse_x = (int) mouse_x;
this.prev_target_mouse_y = this.target_mouse_y = (int) mouse_y;
if (Math.abs(prevXAxis) < deadZone && Math.abs(prevYAxis) < deadZone) {
INPUT_MANAGER.resetMouseTarget(client);
}
if (Math.abs(movement_x) >= dead_zone)
this.mouse_speed_x = movement_x;
if (Math.abs(movementX) >= deadZone)
this.mouseSpeedX = movementX;
else
this.mouse_speed_x = 0.F;
this.mouseSpeedX = 0.F;
if (Math.abs(movement_y) >= dead_zone)
this.mouse_speed_y = movement_y;
if (Math.abs(movementY) >= deadZone)
this.mouseSpeedY = movementY;
else
this.mouse_speed_y = 0.F;
this.mouseSpeedY = 0.F;
} else {
this.mouse_speed_x = 0.F;
this.mouse_speed_y = 0.F;
this.mouseSpeedX = 0.F;
this.mouseSpeedY = 0.F;
}
if (Math.abs(this.mouse_speed_x) >= .05F || Math.abs(this.mouse_speed_y) >= .05F) {
this.target_mouse_x += this.mouse_speed_x * this.config.get_mouse_speed();
this.target_mouse_x = MathHelper.clamp(this.target_mouse_x, 0, client.getWindow().getWidth());
this.target_mouse_y += this.mouse_speed_y * this.config.get_mouse_speed();
this.target_mouse_y = MathHelper.clamp(this.target_mouse_y, 0, client.getWindow().getHeight());
if (Math.abs(this.mouseSpeedX) >= .05F || Math.abs(this.mouseSpeedY) >= .05F) {
InputManager.queueMoveMousePosition(this.mouseSpeedX * this.config.getMouseSpeed(), this.mouseSpeedY * this.config.getMouseSpeed());
}
this.move_mouse_to_closest_slot(client, client.currentScreen);
this.moveMouseToClosestSlot(client, client.currentScreen);
}
this.prev_x_axis = movement_x;
this.prev_y_axis = movement_y;
this.prevXAxis = movementX;
this.prevYAxis = movementY;
}
}
private boolean handle_a_button(@NotNull Screen screen, @NotNull Element focused)
private boolean handleAButton(@NotNull Screen screen, @NotNull Element focused)
{
if (focused instanceof AbstractPressableButtonWidget) {
AbstractPressableButtonWidget button_widget = (AbstractPressableButtonWidget) focused;
button_widget.playDownSound(MinecraftClient.getInstance().getSoundManager());
button_widget.onPress();
AbstractPressableButtonWidget widget = (AbstractPressableButtonWidget) focused;
widget.playDownSound(MinecraftClient.getInstance().getSoundManager());
widget.onPress();
return true;
} else if (focused instanceof SpruceLabelWidget) {
((SpruceLabelWidget) focused).on_press();
((SpruceLabelWidget) focused).onPress();
return true;
} else if (focused instanceof WorldListWidget) {
WorldListWidget list = (WorldListWidget) focused;
@@ -497,9 +490,9 @@ public class LambdaInput
((MultiplayerScreen) screen).connect();
}
} else if (focused instanceof ParentElement) {
Element child_focused = ((ParentElement) focused).getFocused();
if (child_focused != null)
return this.handle_a_button(screen, child_focused);
Element childFocused = ((ParentElement) focused).getFocused();
if (childFocused != null)
return this.handleAButton(screen, childFocused);
}
return false;
}
@@ -510,31 +503,31 @@ public class LambdaInput
* @param screen The current screen.
* @param right True if the right button is pressed, else false.
*/
private boolean handle_left_right(@NotNull Screen screen, boolean right)
private boolean handleLeftRight(@NotNull Screen screen, boolean right)
{
Element focused = screen.getFocused();
if (focused != null)
if (this.handle_right_left_element(focused, right))
return this.change_focus(screen, right);
if (this.handleRightLeftElement(focused, right))
return this.changeFocus(screen, right);
return true;
}
private boolean handle_right_left_element(@NotNull Element element, boolean right)
private boolean handleRightLeftElement(@NotNull Element element, boolean right)
{
if (element instanceof SliderWidget) {
SliderWidget slider = (SliderWidget) element;
slider.keyPressed(right ? 262 : 263, 0, 0);
this.action_gui_cooldown = 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;
} else if (element instanceof AlwaysSelectedEntryListWidget) {
((EntryListWidgetAccessor) element).lambdacontrols_move_selection(right ? 1 : -1);
((EntryListWidgetAccessor) element).lambdacontrols_moveSelection(right ? 1 : -1);
return false;
} else if (element instanceof ParentElement) {
ParentElement entry_list = (ParentElement) element;
Element focused = entry_list.getFocused();
ParentElement entryList = (ParentElement) element;
Element focused = entryList.getFocused();
if (focused == null)
return true;
return this.handle_right_left_element(focused, right);
return this.handleRightLeftElement(focused, right);
}
return true;
}
@@ -547,103 +540,103 @@ public class LambdaInput
* @param value The value of the look.
* @param state The state.
*/
public void handle_look(@NotNull MinecraftClient client, int axis, float value, int state)
public void handleLook(@NotNull MinecraftClient client, int axis, float value, int state)
{
// Handles the look direction.
if (client.player != null) {
double pow_value = Math.pow(value, 4.0);
double powValue = Math.pow(value, 4.0);
if (axis == GLFW_GAMEPAD_AXIS_RIGHT_Y) {
if (state == 2) {
this.target_pitch = client.player.pitch - this.config.get_right_y_axis_sign() * (this.config.get_rotation_speed() * pow_value) * 0.33D;
this.target_pitch = MathHelper.clamp(this.target_pitch, -90.0D, 90.0D);
this.targetPitch = client.player.pitch - this.config.getRightYAxisSign() * (this.config.getRotationSpeed() * powValue) * 0.33D;
this.targetPitch = MathHelper.clamp(this.targetPitch, -90.0D, 90.0D);
} else if (state == 1) {
this.target_pitch = client.player.pitch + this.config.get_right_y_axis_sign() * (this.config.get_rotation_speed() * pow_value) * 0.33D;
this.target_pitch = MathHelper.clamp(this.target_pitch, -90.0D, 90.0D);
this.targetPitch = client.player.pitch + 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 (state == 2) {
this.target_yaw = client.player.yaw - this.config.get_right_x_axis_sign() * (this.config.get_rotation_speed() * pow_value) * 0.33D;
this.targetYaw = client.player.yaw - this.config.getRightXAxisSign() * (this.config.getRotationSpeed() * powValue) * 0.33D;
} else if (state == 1) {
this.target_yaw = client.player.yaw + this.config.get_right_x_axis_sign() * (this.config.get_rotation_speed() * pow_value) * 0.33D;
this.targetYaw = client.player.yaw + this.config.getRightXAxisSign() * (this.config.getRotationSpeed() * powValue) * 0.33D;
}
}
}
}
private boolean change_focus(@NotNull Screen screen, boolean down)
private boolean changeFocus(@NotNull Screen screen, boolean down)
{
if (!screen.changeFocus(down)) {
if (screen.changeFocus(down)) {
this.action_gui_cooldown = 5;
this.actionGuiCooldown = 5;
return false;
}
return true;
} else {
this.action_gui_cooldown = 5;
this.actionGuiCooldown = 5;
return false;
}
}
private static boolean is_screen_interactive(@NotNull Screen screen)
private static boolean isScreenInteractive(@NotNull Screen screen)
{
return !(screen instanceof AdvancementsScreen || screen instanceof AbstractContainerScreen);
return !(screen instanceof AdvancementsScreen || screen instanceof ContainerScreen);
}
// Inspired from https://github.com/MrCrayfish/Controllable/blob/1.14.X/src/main/java/com/mrcrayfish/controllable/client/ControllerInput.java#L686.
private void move_mouse_to_closest_slot(@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.
if (screen instanceof AbstractContainerScreen) {
AbstractContainerScreen inventory_screen = (AbstractContainerScreen) screen;
AbstractContainerScreenAccessor accessor = (AbstractContainerScreenAccessor) inventory_screen;
int gui_left = accessor.lambdacontrols_get_x();
int gui_top = accessor.lambdacontrols_get_y();
int mouse_x = (int) (target_mouse_x * (double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth());
int mouse_y = (int) (target_mouse_y * (double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight());
if (screen instanceof ContainerScreen) {
ContainerScreen inventoryScreen = (ContainerScreen) screen;
ContainerScreenAccessor accessor = (ContainerScreenAccessor) inventoryScreen;
int guiLeft = accessor.lambdacontrols_getX();
int guiTop = accessor.lambdacontrols_getY();
int mouseX = (int) (targetMouseX * (double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth());
int mouseY = (int) (targetMouseY * (double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight());
// Finds the closest slot in the GUI within 14 pixels.
Optional<Pair<Slot, Double>> closest_slot = inventory_screen.getContainer().slotList.parallelStream()
Optional<Pair<Slot, Double>> closestSlot = inventoryScreen.getContainer().slots.parallelStream()
.map(slot -> {
int pos_x = gui_left + slot.xPosition + 8;
int pos_y = gui_top + slot.yPosition + 8;
int x = guiLeft + slot.xPosition + 8;
int y = guiTop + slot.yPosition + 8;
// Distance between the slot and the cursor.
double distance = Math.sqrt(Math.pow(pos_x - mouse_x, 2) + Math.pow(pos_y - mouse_y, 2));
double distance = Math.sqrt(Math.pow(x - mouseX, 2) + Math.pow(y - mouseY, 2));
return Pair.of(slot, distance);
}).filter(entry -> entry.get_value() <= 14.0)
.min(Comparator.comparingDouble(Pair::get_value));
}).filter(entry -> entry.value <= 14.0)
.min(Comparator.comparingDouble(p -> p.value));
if (closest_slot.isPresent()) {
Slot slot = closest_slot.get().get_key();
if (closestSlot.isPresent()) {
Slot slot = closestSlot.get().key;
if (slot.hasStack() || !client.player.inventory.getMainHandStack().isEmpty()) {
int slot_center_x_scaled = gui_left + slot.xPosition + 8;
int slot_center_y_scaled = gui_top + slot.yPosition + 8;
int slot_center_x = (int) (slot_center_x_scaled / ((double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth()));
int slot_center_y = (int) (slot_center_y_scaled / ((double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight()));
double delta_x = slot_center_x - target_mouse_x;
double delta_y = slot_center_y - target_mouse_y;
int slotCenterXScaled = guiLeft + slot.xPosition + 8;
int slotCenterYScaled = guiTop + slot.yPosition + 8;
int slotCenterX = (int) (slotCenterXScaled / ((double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth()));
int slotCenterY = (int) (slotCenterYScaled / ((double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight()));
double deltaX = slotCenterX - targetMouseX;
double deltaY = slotCenterY - targetMouseY;
if (mouse_x != slot_center_x_scaled || mouse_y != slot_center_y_scaled) {
this.target_mouse_x += delta_x * 0.75;
this.target_mouse_y += delta_y * 0.75;
if (mouseX != slotCenterXScaled || mouseY != slotCenterYScaled) {
this.targetMouseX += deltaX * 0.75;
this.targetMouseY += deltaY * 0.75;
} else {
this.mouse_speed_x *= 0.3F;
this.mouse_speed_y *= 0.3F;
this.mouseSpeedX *= 0.3F;
this.mouseSpeedY *= 0.3F;
}
this.mouse_speed_x *= .75F;
this.mouse_speed_y *= .75F;
this.mouseSpeedX *= .75F;
this.mouseSpeedY *= .75F;
} else {
this.mouse_speed_x *= .1F;
this.mouse_speed_y *= .1F;
this.mouseSpeedX *= .1F;
this.mouseSpeedY *= .1F;
}
} else {
this.mouse_speed_x *= .3F;
this.mouse_speed_y *= .3F;
this.mouseSpeedX *= .3F;
this.mouseSpeedY *= .3F;
}
} else {
this.mouse_speed_x = 0.F;
this.mouse_speed_y = 0.F;
this.mouseSpeedX = 0.F;
this.mouseSpeedY = 0.F;
}
}
}

View File

@@ -31,10 +31,10 @@ public class LambdaControlsCompat
*/
public static void init(@NotNull LambdaControlsClient mod)
{
if (FabricLoader.getInstance().isModLoaded("okzoomer") && LambdaReflection.does_class_exist(OkZoomerCompat.OKZOOMER_CLASS_PATH)) {
if (FabricLoader.getInstance().isModLoaded("okzoomer") && LambdaReflection.doesClassExist(OkZoomerCompat.OKZOOMER_CLASS_PATH)) {
mod.log("Adding okzoomer compatibility...");
new OkZoomerCompat().handle(mod);
}
InputManager.load_button_bindings(mod.config);
InputManager.loadButtonBindings(mod.config);
}
}

View File

@@ -12,7 +12,6 @@ package me.lambdaurora.lambdacontrols.client.compat;
import io.github.joaoh1.okzoomer.OkZoomer;
import me.lambdaurora.lambdacontrols.client.LambdaControlsClient;
import me.lambdaurora.lambdacontrols.client.controller.ButtonBinding;
import me.lambdaurora.lambdacontrols.client.controller.InputManager;
import org.jetbrains.annotations.NotNull;
import org.lwjgl.glfw.GLFW;
@@ -30,8 +29,12 @@ public class OkZoomerCompat implements CompatHandler
@Override
public void handle(@NotNull LambdaControlsClient mod)
{
ButtonBinding binding = InputManager.register_binding(new ButtonBinding("zoom", new int[]{GLFW.GLFW_GAMEPAD_BUTTON_DPAD_UP, GLFW.GLFW_GAMEPAD_BUTTON_X}, true));
binding.set_key_binding(OkZoomer.zoomKeyBinding);
ButtonBinding.MISC_CATEGORY.register_binding(binding);
new ButtonBinding.Builder("zoom")
.buttons(GLFW.GLFW_GAMEPAD_BUTTON_DPAD_UP, GLFW.GLFW_GAMEPAD_BUTTON_X)
.onlyInGame()
.cooldown(true)
.category(ButtonBinding.MISC_CATEGORY)
.linkKeybind(OkZoomer.zoomKeyBinding)
.register();
}
}

View File

@@ -14,16 +14,18 @@ import net.minecraft.client.MinecraftClient;
import net.minecraft.client.options.GameOptions;
import net.minecraft.client.options.KeyBinding;
import net.minecraft.client.resource.language.I18n;
import org.aperlambda.lambdacommon.Identifier;
import org.aperlambda.lambdacommon.utils.Nameable;
import org.aperlambda.lambdacommon.utils.function.PairPredicate;
import org.aperlambda.lambdacommon.utils.function.Predicates;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.lwjgl.glfw.GLFW;
import java.util.*;
import java.util.stream.Collectors;
import static me.lambdaurora.lambdacontrols.client.controller.InputManager.register_binding;
import static me.lambdaurora.lambdacontrols.client.controller.InputManager.register_default_category;
import static me.lambdaurora.lambdacontrols.client.controller.InputManager.registerDefaultCategory;
import static org.lwjgl.glfw.GLFW.*;
/**
* Represents a button binding.
@@ -40,53 +42,66 @@ public class ButtonBinding implements Nameable
public static final ButtonCategory MULTIPLAYER_CATEGORY;
public static final ButtonCategory MISC_CATEGORY;
public static final ButtonBinding ATTACK = register_binding(new ButtonBinding("attack", new int[]{axis_as_button(GLFW.GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER, true)}, false));
public static final ButtonBinding BACK = register_binding(new ButtonBinding("back", new int[]{axis_as_button(GLFW.GLFW_GAMEPAD_AXIS_LEFT_Y, false)}, false));
public static final ButtonBinding CHAT = register_binding(new ButtonBinding("chat", new int[]{GLFW.GLFW_GAMEPAD_BUTTON_DPAD_RIGHT}, true));
public static final ButtonBinding DROP_ITEM = register_binding(new ButtonBinding("drop_item", new int[]{GLFW.GLFW_GAMEPAD_BUTTON_B}, true));
public static final ButtonBinding FORWARD = register_binding(new ButtonBinding("forward", new int[]{axis_as_button(GLFW.GLFW_GAMEPAD_AXIS_LEFT_Y, true)}, false));
public static final ButtonBinding HOTBAR_LEFT = register_binding(new ButtonBinding("hotbar_left", new int[]{GLFW.GLFW_GAMEPAD_BUTTON_LEFT_BUMPER},
Collections.singletonList(InputHandlers.handle_hotbar(false)), true));
public static final ButtonBinding HOTBAR_RIGHT = register_binding(new ButtonBinding("hotbar_right", new int[]{GLFW.GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER},
Collections.singletonList(InputHandlers.handle_hotbar(true)), true));
public static final ButtonBinding INVENTORY = register_binding(new ButtonBinding("inventory", new int[]{GLFW.GLFW_GAMEPAD_BUTTON_Y}, true));
public static final ButtonBinding JUMP = register_binding(new ButtonBinding("jump", new int[]{GLFW.GLFW_GAMEPAD_BUTTON_A}, false));
public static final ButtonBinding LEFT = register_binding(new ButtonBinding("left", new int[]{axis_as_button(GLFW.GLFW_GAMEPAD_AXIS_LEFT_X, false)}, false));
public static final ButtonBinding PAUSE_GAME = register_binding(new ButtonBinding("pause_game", new int[]{GLFW.GLFW_GAMEPAD_BUTTON_START},
Collections.singletonList(InputHandlers::handle_pause_game), true));
public static final ButtonBinding PICK_BLOCK = register_binding(new ButtonBinding("pick_block", new int[]{GLFW.GLFW_GAMEPAD_BUTTON_DPAD_LEFT}, true));
public static final ButtonBinding PLAYER_LIST = register_binding(new ButtonBinding("player_list", new int[]{GLFW.GLFW_GAMEPAD_BUTTON_BACK}, false));
public static final ButtonBinding RIGHT = register_binding(new ButtonBinding("right", new int[]{axis_as_button(GLFW.GLFW_GAMEPAD_AXIS_LEFT_X, true)}, false));
public static final ButtonBinding SCREENSHOT = register_binding(new ButtonBinding("screenshot", new int[]{GLFW.GLFW_GAMEPAD_BUTTON_DPAD_UP, GLFW.GLFW_GAMEPAD_BUTTON_A},
Collections.singletonList(InputHandlers::handle_screenshot), true));
public static final ButtonBinding SMOOTH_CAMERA = register_binding(new ButtonBinding("toggle_smooth_camera", new int[]{-1}, true));
public static final ButtonBinding SNEAK = register_binding(new ButtonBinding("sneak", new int[]{GLFW.GLFW_GAMEPAD_BUTTON_RIGHT_THUMB},
Arrays.asList(PressAction.DEFAULT_ACTION, InputHandlers::handle_toggle_sneak), true));
public static final ButtonBinding SPRINT = register_binding(new ButtonBinding("sprint", new int[]{GLFW.GLFW_GAMEPAD_BUTTON_LEFT_THUMB}, false));
public static final ButtonBinding SWAP_HANDS = register_binding(new ButtonBinding("swap_hands", new int[]{GLFW.GLFW_GAMEPAD_BUTTON_X}, true));
public static final ButtonBinding TOGGLE_PERSPECTIVE = register_binding(new ButtonBinding("toggle_perspective", new int[]{GLFW.GLFW_GAMEPAD_BUTTON_DPAD_UP, GLFW.GLFW_GAMEPAD_BUTTON_Y}, true));
public static final ButtonBinding USE = register_binding(new ButtonBinding("use", new int[]{axis_as_button(GLFW.GLFW_GAMEPAD_AXIS_LEFT_TRIGGER, true)}, false));
public static final ButtonBinding ATTACK = new Builder("attack").buttons(axisAsButton(GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER, true)).onlyInGame().register();
public static final ButtonBinding BACK = new Builder("back").buttons(axisAsButton(GLFW_GAMEPAD_AXIS_LEFT_Y, false)).onlyInGame().register();
public static final ButtonBinding CHAT = new Builder("chat").buttons(GLFW_GAMEPAD_BUTTON_DPAD_RIGHT).onlyInGame().cooldown(true).register();
public static final ButtonBinding DROP_ITEM = new Builder("drop_item").buttons(GLFW_GAMEPAD_BUTTON_B).onlyInGame().cooldown(true).register();
public static final ButtonBinding FORWARD = new Builder("forward").buttons(axisAsButton(GLFW_GAMEPAD_AXIS_LEFT_Y, true)).onlyInGame().register();
public static final ButtonBinding HOTBAR_LEFT = new Builder("hotbar_left").buttons(GLFW_GAMEPAD_BUTTON_LEFT_BUMPER)
.action(InputHandlers.handleHotbar(false)).onlyInGame().cooldown(true).register();
public static final ButtonBinding HOTBAR_RIGHT = new Builder("hotbar_right").buttons(GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER)
.action(InputHandlers.handleHotbar(true)).onlyInGame().cooldown(true).register();
public static final ButtonBinding INVENTORY = new Builder("inventory").buttons(GLFW_GAMEPAD_BUTTON_Y).onlyInGame().cooldown(true).register();
public static final ButtonBinding JUMP = new Builder("jump").buttons(GLFW_GAMEPAD_BUTTON_A).onlyInGame().register();
public static final ButtonBinding LEFT = new Builder("left").buttons(axisAsButton(GLFW_GAMEPAD_AXIS_LEFT_X, false)).onlyInGame().register();
public static final ButtonBinding PAUSE_GAME = new Builder("pause_game").buttons(GLFW_GAMEPAD_BUTTON_START).action(InputHandlers::handlePauseGame).cooldown(true).register();
public static final ButtonBinding PICK_BLOCK = new Builder("pick_block").buttons(GLFW_GAMEPAD_BUTTON_DPAD_LEFT).onlyInGame().cooldown(true).register();
public static final ButtonBinding PLAYER_LIST = new Builder("player_list").buttons(GLFW_GAMEPAD_BUTTON_BACK).onlyInGame().register();
public static final ButtonBinding RIGHT = new Builder("right").buttons(axisAsButton(GLFW_GAMEPAD_AXIS_LEFT_X, true)).register();
public static final ButtonBinding SCREENSHOT = new Builder("screenshot").buttons(GLFW_GAMEPAD_BUTTON_DPAD_UP, GLFW_GAMEPAD_BUTTON_A)
.action(InputHandlers::handleScreenshot).cooldown(true).register();
public static final ButtonBinding SLOT_DOWN = new Builder("slot_down").buttons(GLFW_GAMEPAD_BUTTON_DPAD_DOWN)
.action(InputHandlers.handleInventorySlotPad(1)).onlyInInventory().cooldown(true).register();
public static final ButtonBinding SLOT_LEFT = new Builder("slot_left").buttons(GLFW_GAMEPAD_BUTTON_DPAD_LEFT)
.action(InputHandlers.handleInventorySlotPad(3)).onlyInInventory().cooldown(true).register();
public static final ButtonBinding SLOT_RIGHT = new Builder("slot_right").buttons(GLFW_GAMEPAD_BUTTON_DPAD_RIGHT)
.action(InputHandlers.handleInventorySlotPad(2)).onlyInInventory().cooldown(true).register();
public static final ButtonBinding SLOT_UP = new Builder("slot_up").buttons(GLFW_GAMEPAD_BUTTON_DPAD_UP)
.action(InputHandlers.handleInventorySlotPad(0)).onlyInInventory().cooldown(true).register();
public static final ButtonBinding SMOOTH_CAMERA = new Builder("toggle_smooth_camera").cooldown(true).register();
public static final ButtonBinding SNEAK = new Builder("sneak").buttons(GLFW_GAMEPAD_BUTTON_RIGHT_THUMB)
.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 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)
.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)
.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 USE = new Builder("use").buttons(axisAsButton(GLFW_GAMEPAD_AXIS_LEFT_TRIGGER, true)).register();
private int[] button;
private int[] default_button;
private String key;
private KeyBinding minecraft_key_binding = null;
private List<PressAction> actions = new ArrayList<>(Collections.singletonList(PressAction.DEFAULT_ACTION));
private boolean has_cooldown;
private int cooldown = 0;
private int[] button;
private int[] defaultButton;
private String key;
private KeyBinding mcKeyBinding = null;
protected PairPredicate<MinecraftClient, ButtonBinding> filter;
private List<PressAction> actions = new ArrayList<>(Collections.singletonList(PressAction.DEFAULT_ACTION));
private boolean hasCooldown;
private int cooldown = 0;
boolean pressed = false;
public ButtonBinding(@NotNull String key, int[] default_button, @NotNull List<PressAction> actions, boolean has_cooldown)
public ButtonBinding(@NotNull String key, int[] defaultButton, @NotNull List<PressAction> actions, PairPredicate<MinecraftClient, ButtonBinding> filter, boolean hasCooldown)
{
this.set_button(this.default_button = default_button);
this.setButton(this.defaultButton = defaultButton);
this.key = key;
this.filter = filter;
this.actions.addAll(actions);
this.has_cooldown = has_cooldown;
this.hasCooldown = hasCooldown;
}
public ButtonBinding(@NotNull String key, int[] default_button, boolean has_cooldown)
public ButtonBinding(@NotNull String key, int[] defaultButton, boolean hasCooldown)
{
this(key, default_button, Collections.emptyList(), has_cooldown);
this(key, defaultButton, Collections.emptyList(), Predicates.pairAlwaysTrue(), hasCooldown);
}
/**
@@ -94,7 +109,7 @@ public class ButtonBinding implements Nameable
*
* @return The bound button.
*/
public int[] get_button()
public int[] getButton()
{
return this.button;
}
@@ -104,12 +119,12 @@ public class ButtonBinding implements Nameable
*
* @param button The bound button.
*/
public void set_button(int[] button)
public void setButton(int[] button)
{
this.button = button;
if (InputManager.has_binding(this))
InputManager.sort_bindings();
if (InputManager.hasBinding(this))
InputManager.sortBindings();
}
/**
@@ -118,9 +133,9 @@ public class ButtonBinding implements Nameable
* @param button The button to check.
* @return True if the bound button is the specified button, else false.
*/
public boolean is_button(int[] button)
public boolean isButton(int[] button)
{
return InputManager.are_buttons_equivalent(button, this.button);
return InputManager.areButtonsEquivalent(button, this.button);
}
/**
@@ -128,7 +143,7 @@ public class ButtonBinding implements Nameable
*
* @return True if the button is down, else false.
*/
public boolean is_button_down()
public boolean isButtonDown()
{
return this.pressed;
}
@@ -138,7 +153,7 @@ public class ButtonBinding implements Nameable
*
* @return True if this button binding is bound, else false.
*/
public boolean is_not_bound()
public boolean isNotBound()
{
return this.button.length == 0 || this.button[0] == -1;
}
@@ -148,9 +163,9 @@ public class ButtonBinding implements Nameable
*
* @return The default button.
*/
public int[] get_default_button()
public int[] getDefaultButton()
{
return this.default_button;
return this.defaultButton;
}
/**
@@ -158,9 +173,9 @@ public class ButtonBinding implements Nameable
*
* @return True if the assigned button is the default button, else false.
*/
public boolean is_default()
public boolean isDefault()
{
return this.button.length == this.default_button.length && InputManager.are_buttons_equivalent(this.button, this.default_button);
return this.button.length == this.defaultButton.length && InputManager.areButtonsEquivalent(this.button, this.defaultButton);
}
/**
@@ -168,7 +183,8 @@ public class ButtonBinding implements Nameable
*
* @return The button code.
*/
public @NotNull String get_button_code()
public @NotNull
String getButtonCode()
{
return Arrays.stream(this.button)
.mapToObj(btn -> Integer.valueOf(btn).toString())
@@ -178,11 +194,22 @@ public class ButtonBinding implements Nameable
/**
* Sets the key binding to emulate with this button binding.
*
* @param key_binding The optional key binding.
* @param keyBinding The optional key binding.
*/
public void set_key_binding(@Nullable KeyBinding key_binding)
public void setKeyBinding(@Nullable KeyBinding keyBinding)
{
this.minecraft_key_binding = key_binding;
this.mcKeyBinding = keyBinding;
}
/**
* Returns whether the button binding is available in the current context.
*
* @param client The client instance.
* @return True if the button binding is available, else false.
*/
public boolean isAvailable(@NotNull MinecraftClient client)
{
return this.filter.test(client, this);
}
/**
@@ -190,7 +217,7 @@ public class ButtonBinding implements Nameable
*/
public void update()
{
if (this.has_cooldown && this.cooldown > 0)
if (this.hasCooldown && this.cooldown > 0)
this.cooldown--;
}
@@ -202,9 +229,9 @@ public class ButtonBinding implements Nameable
*/
public void handle(@NotNull MinecraftClient client, @NotNull ButtonState state)
{
if (state == ButtonState.REPEAT && this.has_cooldown && this.cooldown != 0)
if (state == ButtonState.REPEAT && this.hasCooldown && this.cooldown != 0)
return;
if (this.has_cooldown && state.is_pressed()) {
if (this.hasCooldown && state.isPressed()) {
this.cooldown = 5;
}
@@ -215,7 +242,7 @@ public class ButtonBinding implements Nameable
}
@Override
public @NotNull String get_name()
public @NotNull String getName()
{
return this.key;
}
@@ -225,9 +252,10 @@ public class ButtonBinding implements Nameable
*
* @return The translation key.
*/
public @NotNull String get_translation_key()
public @NotNull
String getTranslationKey()
{
return "lambdacontrols.action." + this.get_name();
return "lambdacontrols.action." + this.getName();
}
/**
@@ -235,9 +263,10 @@ public class ButtonBinding implements Nameable
*
* @return The key binding equivalent.
*/
public @NotNull Optional<KeyBinding> as_key_binding()
public @NotNull
Optional<KeyBinding> asKeyBinding()
{
return Optional.ofNullable(this.minecraft_key_binding);
return Optional.ofNullable(this.mcKeyBinding);
}
/**
@@ -247,7 +276,7 @@ public class ButtonBinding implements Nameable
* @param positive True if the axis part is positive, else false.
* @return The axis as a button.
*/
public static int axis_as_button(int axis, boolean positive)
public static int axisAsButton(int axis, boolean positive)
{
return positive ? 100 + axis : 200 + axis;
}
@@ -258,31 +287,31 @@ public class ButtonBinding implements Nameable
* @param button The raw button code.
* @return The second Joycon's button code.
*/
public static int controller2_button(int button)
public static int controller2Button(int button)
{
return 500 + button;
}
public static void init(@NotNull GameOptions options)
{
ATTACK.minecraft_key_binding = options.keyAttack;
BACK.minecraft_key_binding = options.keyBack;
CHAT.minecraft_key_binding = options.keyChat;
DROP_ITEM.minecraft_key_binding = options.keyDrop;
FORWARD.minecraft_key_binding = options.keyForward;
INVENTORY.minecraft_key_binding = options.keyInventory;
JUMP.minecraft_key_binding = options.keyJump;
LEFT.minecraft_key_binding = options.keyLeft;
PICK_BLOCK.minecraft_key_binding = options.keyPickItem;
PLAYER_LIST.minecraft_key_binding = options.keyPlayerList;
RIGHT.minecraft_key_binding = options.keyRight;
SCREENSHOT.minecraft_key_binding = options.keyScreenshot;
SMOOTH_CAMERA.minecraft_key_binding = options.keySmoothCamera;
SNEAK.minecraft_key_binding = options.keySneak;
SPRINT.minecraft_key_binding = options.keySprint;
SWAP_HANDS.minecraft_key_binding = options.keySwapHands;
TOGGLE_PERSPECTIVE.minecraft_key_binding = options.keyTogglePerspective;
USE.minecraft_key_binding = options.keyUse;
ATTACK.mcKeyBinding = options.keyAttack;
BACK.mcKeyBinding = options.keyBack;
CHAT.mcKeyBinding = options.keyChat;
DROP_ITEM.mcKeyBinding = options.keyDrop;
FORWARD.mcKeyBinding = options.keyForward;
INVENTORY.mcKeyBinding = options.keyInventory;
JUMP.mcKeyBinding = options.keyJump;
LEFT.mcKeyBinding = options.keyLeft;
PICK_BLOCK.mcKeyBinding = options.keyPickItem;
PLAYER_LIST.mcKeyBinding = options.keyPlayerList;
RIGHT.mcKeyBinding = options.keyRight;
SCREENSHOT.mcKeyBinding = options.keyScreenshot;
SMOOTH_CAMERA.mcKeyBinding = options.keySmoothCamera;
SNEAK.mcKeyBinding = options.keySneak;
SPRINT.mcKeyBinding = options.keySprint;
SWAP_HANDS.mcKeyBinding = options.keySwapHands;
TOGGLE_PERSPECTIVE.mcKeyBinding = options.keyTogglePerspective;
USE.mcKeyBinding = options.keyUse;
}
/**
@@ -291,40 +320,41 @@ public class ButtonBinding implements Nameable
* @param button The button.
* @return The localized name of the button.
*/
public static @NotNull String get_localized_button_name(int button)
public static @NotNull
String getLocalizedButtonName(int button)
{
switch (button % 500) {
case -1:
return I18n.translate("key.keyboard.unknown");
case GLFW.GLFW_GAMEPAD_BUTTON_A:
case GLFW_GAMEPAD_BUTTON_A:
return I18n.translate("lambdacontrols.button.a");
case GLFW.GLFW_GAMEPAD_BUTTON_B:
case GLFW_GAMEPAD_BUTTON_B:
return I18n.translate("lambdacontrols.button.b");
case GLFW.GLFW_GAMEPAD_BUTTON_X:
case GLFW_GAMEPAD_BUTTON_X:
return I18n.translate("lambdacontrols.button.x");
case GLFW.GLFW_GAMEPAD_BUTTON_Y:
case GLFW_GAMEPAD_BUTTON_Y:
return I18n.translate("lambdacontrols.button.y");
case GLFW.GLFW_GAMEPAD_BUTTON_LEFT_BUMPER:
case GLFW_GAMEPAD_BUTTON_LEFT_BUMPER:
return I18n.translate("lambdacontrols.button.left_bumper");
case GLFW.GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER:
case GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER:
return I18n.translate("lambdacontrols.button.right_bumper");
case GLFW.GLFW_GAMEPAD_BUTTON_BACK:
case GLFW_GAMEPAD_BUTTON_BACK:
return I18n.translate("lambdacontrols.button.back");
case GLFW.GLFW_GAMEPAD_BUTTON_START:
case GLFW_GAMEPAD_BUTTON_START:
return I18n.translate("lambdacontrols.button.start");
case GLFW.GLFW_GAMEPAD_BUTTON_GUIDE:
case GLFW_GAMEPAD_BUTTON_GUIDE:
return I18n.translate("lambdacontrols.button.guide");
case GLFW.GLFW_GAMEPAD_BUTTON_LEFT_THUMB:
case GLFW_GAMEPAD_BUTTON_LEFT_THUMB:
return I18n.translate("lambdacontrols.button.left_thumb");
case GLFW.GLFW_GAMEPAD_BUTTON_RIGHT_THUMB:
case GLFW_GAMEPAD_BUTTON_RIGHT_THUMB:
return I18n.translate("lambdacontrols.button.right_thumb");
case GLFW.GLFW_GAMEPAD_BUTTON_DPAD_UP:
case GLFW_GAMEPAD_BUTTON_DPAD_UP:
return I18n.translate("lambdacontrols.button.dpad_up");
case GLFW.GLFW_GAMEPAD_BUTTON_DPAD_RIGHT:
case GLFW_GAMEPAD_BUTTON_DPAD_RIGHT:
return I18n.translate("lambdacontrols.button.dpad_right");
case GLFW.GLFW_GAMEPAD_BUTTON_DPAD_DOWN:
case GLFW_GAMEPAD_BUTTON_DPAD_DOWN:
return I18n.translate("lambdacontrols.button.dpad_down");
case GLFW.GLFW_GAMEPAD_BUTTON_DPAD_LEFT:
case GLFW_GAMEPAD_BUTTON_DPAD_LEFT:
return I18n.translate("lambdacontrols.button.dpad_left");
case 100:
return I18n.translate("lambdacontrols.axis.left_x+");
@@ -352,7 +382,7 @@ public class ButtonBinding implements Nameable
}
static {
MOVEMENT_CATEGORY = register_default_category("key.categories.movement", category -> category.register_all_bindings(
MOVEMENT_CATEGORY = registerDefaultCategory("key.categories.movement", category -> category.registerAllBindings(
ButtonBinding.FORWARD,
ButtonBinding.BACK,
ButtonBinding.LEFT,
@@ -360,24 +390,207 @@ public class ButtonBinding implements Nameable
ButtonBinding.JUMP,
ButtonBinding.SNEAK,
ButtonBinding.SPRINT));
GAMEPLAY_CATEGORY = register_default_category("key.categories.gameplay", category -> category.register_all_bindings(
GAMEPLAY_CATEGORY = registerDefaultCategory("key.categories.gameplay", category -> category.registerAllBindings(
ButtonBinding.ATTACK,
ButtonBinding.PICK_BLOCK,
ButtonBinding.USE
));
INVENTORY_CATEGORY = register_default_category("key.categories.inventory", category -> category.register_all_bindings(
INVENTORY_CATEGORY = registerDefaultCategory("key.categories.inventory", category -> category.registerAllBindings(
ButtonBinding.DROP_ITEM,
ButtonBinding.HOTBAR_LEFT,
ButtonBinding.HOTBAR_RIGHT,
ButtonBinding.INVENTORY,
ButtonBinding.SWAP_HANDS
));
MULTIPLAYER_CATEGORY = register_default_category("key.categories.multiplayer",
category -> category.register_all_bindings(ButtonBinding.CHAT, ButtonBinding.PLAYER_LIST));
MISC_CATEGORY = register_default_category("key.categories.misc", category -> category.register_all_bindings(
MULTIPLAYER_CATEGORY = registerDefaultCategory("key.categories.multiplayer",
category -> category.registerAllBindings(ButtonBinding.CHAT, ButtonBinding.PLAYER_LIST));
MISC_CATEGORY = registerDefaultCategory("key.categories.misc", category -> category.registerAllBindings(
ButtonBinding.SCREENSHOT,
//SMOOTH_CAMERA,
ButtonBinding.TOGGLE_PERSPECTIVE
));
}
/**
* Represents a quick {@link ButtonBinding} builder.
*
* @author LambdAurora
* @version 1.1.0
* @since 1.1.0
*/
public static class Builder
{
private final String key;
private int[] buttons = new int[0];
private List<PressAction> actions = new ArrayList<>();
private PairPredicate<MinecraftClient, ButtonBinding> filter = Predicates.pairAlwaysTrue();
private boolean cooldown = false;
private ButtonCategory category = null;
private KeyBinding mcBinding = null;
/**
* This constructor shouldn't be used for other mods.
*
* @param key The key with format {@code "<namespace>.<name>"}.
*/
public Builder(@NotNull String key)
{
this.key = key;
this.unbound();
}
public Builder(@NotNull Identifier identifier)
{
this(identifier.getNamespace() + "." + identifier.getName());
}
public Builder(@NotNull net.minecraft.util.Identifier identifier)
{
this(new Identifier(identifier.toString()));
}
/**
* Defines the default buttons of the {@link ButtonBinding}.
*
* @param buttons The default buttons.
* @return The builder instance.
*/
public Builder buttons(int... buttons)
{
this.buttons = buttons;
return this;
}
/**
* Sets the {@link ButtonBinding} to unbound.
*
* @return The builder instance.
*/
public Builder unbound()
{
return this.buttons(-1);
}
/**
* Adds the actions to the {@link ButtonBinding}.
*
* @param actions The actions to add.
* @return The builder instance.
*/
public Builder actions(@NotNull PressAction... actions)
{
this.actions.addAll(Arrays.asList(actions));
return this;
}
/**
* Adds an action to the {@link ButtonBinding}.
*
* @param action The action to add.
* @return The builder instance.
*/
public Builder action(@NotNull PressAction action)
{
this.actions.add(action);
return this;
}
/**
* Sets a filter for the {@link ButtonBinding}.
*
* @param filter The filter.
* @return The builder instance.
*/
public Builder filter(@NotNull PairPredicate<MinecraftClient, ButtonBinding> filter)
{
this.filter = filter;
return this;
}
/**
* Sets the filter of {@link ButtonBinding} to only in game.
*
* @return The builder instance.
* @see #filter(PairPredicate)
* @see InputHandlers#inGame(MinecraftClient, ButtonBinding)
*/
public Builder onlyInGame()
{
return this.filter(InputHandlers::inGame);
}
/**
* Sets the filter of {@link ButtonBinding} to only in inventory.
*
* @return The builder instance.
* @see #filter(PairPredicate)
* @see InputHandlers#inInventory(MinecraftClient, ButtonBinding)
*/
public Builder onlyInInventory()
{
return this.filter(InputHandlers::inInventory);
}
/**
* Sets whether the {@link ButtonBinding} has a cooldown or not.
*
* @param cooldown True if the {@link ButtonBinding} has a cooldown, else false.
* @return The builder instance.
*/
public Builder cooldown(boolean cooldown)
{
this.cooldown = cooldown;
return this;
}
/**
* Sets the category of the {@link ButtonBinding}.
*
* @param category The category.
* @return The builder instance.
*/
public Builder category(@Nullable ButtonCategory category)
{
this.category = category;
return this;
}
/**
* Sets the keybinding linked to the {@link ButtonBinding}.
*
* @param binding The keybinding to link.
* @return The builder instance.
*/
public Builder linkKeybind(@Nullable KeyBinding binding)
{
this.mcBinding = binding;
return this;
}
/**
* Builds the {@link ButtonBinding}.
*
* @return The built {@link ButtonBinding}.
*/
public ButtonBinding build()
{
ButtonBinding binding = new ButtonBinding(this.key, this.buttons, this.actions, this.filter, this.cooldown);
if (this.category != null)
this.category.registerBinding(binding);
if (this.mcBinding != null)
binding.setKeyBinding(this.mcBinding);
return binding;
}
/**
* Builds and registers the {@link ButtonBinding}.
*
* @return The built {@link ButtonBinding}.
* @see #build()
*/
public ButtonBinding register()
{
return InputManager.registerBinding(this.build());
}
}
}

View File

@@ -43,21 +43,21 @@ public class ButtonCategory implements Identifiable
this(id, 100);
}
public void register_binding(@NotNull ButtonBinding binding)
public void registerBinding(@NotNull ButtonBinding binding)
{
if (this.bindings.contains(binding))
throw new IllegalStateException("Cannot register twice a button binding in the same category.");
this.bindings.add(binding);
}
public void register_all_bindings(@NotNull ButtonBinding... bindings)
public void registerAllBindings(@NotNull ButtonBinding... bindings)
{
this.register_all_bindings(Arrays.asList(bindings));
this.registerAllBindings(Arrays.asList(bindings));
}
public void register_all_bindings(@NotNull List<ButtonBinding> bindings)
public void registerAllBindings(@NotNull List<ButtonBinding> bindings)
{
bindings.forEach(this::register_binding);
bindings.forEach(this::registerBinding);
}
/**
@@ -65,7 +65,7 @@ public class ButtonCategory implements Identifiable
*
* @return The bindings assigned to this category.
*/
public @NotNull List<ButtonBinding> get_bindings()
public @NotNull List<ButtonBinding> getBindings()
{
return Collections.unmodifiableList(this.bindings);
}
@@ -77,12 +77,12 @@ public class ButtonCategory implements Identifiable
*
* @return The translated name.
*/
public @NotNull String get_translated_name()
public @NotNull String getTranslatedName()
{
if (this.id.get_namespace().equals("minecraft"))
return I18n.translate(this.id.get_name());
if (this.id.getNamespace().equals("minecraft"))
return I18n.translate(this.id.getName());
else
return I18n.translate(this.id.get_namespace() + "." + this.id.get_name());
return I18n.translate(this.id.getNamespace() + "." + this.id.getName());
}
/**
@@ -91,13 +91,13 @@ public class ButtonCategory implements Identifiable
*
* @return The priority of this category.
*/
public int get_priority()
public int getPriority()
{
return this.priority;
}
@Override
public @NotNull Identifier get_identifier()
public @NotNull Identifier getIdentifier()
{
return this.id;
}

View File

@@ -52,7 +52,7 @@ public class Controller implements Nameable
*
* @return The identifier of this controller.
*/
public int get_id()
public int getId()
{
return this.id;
}
@@ -62,7 +62,7 @@ public class Controller implements Nameable
*
* @return The controller's GUID.
*/
public String get_guid()
public String getGuid()
{
String guid = GLFW.glfwGetJoystickGUID(this.id);
return guid == null ? "" : guid;
@@ -73,7 +73,7 @@ public class Controller implements Nameable
*
* @return True if this controller is connected, else false.
*/
public boolean is_connected()
public boolean isConnected()
{
return GLFW.glfwJoystickPresent(this.id);
}
@@ -83,9 +83,9 @@ public class Controller implements Nameable
*
* @return True if this controller is a gamepad, else false.
*/
public boolean is_gamepad()
public boolean isGamepad()
{
return this.is_connected() && GLFW.glfwJoystickIsGamepad(this.id);
return this.isConnected() && GLFW.glfwJoystickIsGamepad(this.id);
}
/**
@@ -94,10 +94,10 @@ public class Controller implements Nameable
* @return The controller's name.
*/
@Override
public @NotNull String get_name()
public @NotNull String getName()
{
String name = this.is_gamepad() ? GLFW.glfwGetGamepadName(this.id) : GLFW.glfwGetJoystickName(this.id);
return name == null ? String.valueOf(this.get_id()) : name;
String name = this.isGamepad() ? GLFW.glfwGetGamepadName(this.id) : GLFW.glfwGetJoystickName(this.id);
return name == null ? String.valueOf(this.getId()) : name;
}
/**
@@ -105,15 +105,15 @@ public class Controller implements Nameable
*
* @return The state of the controller input.
*/
public GLFWGamepadState get_state()
public GLFWGamepadState getState()
{
GLFWGamepadState state = GLFWGamepadState.create();
if (this.is_gamepad())
if (this.isGamepad())
GLFW.glfwGetGamepadState(this.id, state);
return state;
}
public static @NotNull Controller by_id(int id)
public static @NotNull Controller byId(int id)
{
if (id > GLFW.GLFW_JOYSTICK_LAST) {
LambdaControlsClient.get().log("Controller '" + id + "' doesn't exist.");
@@ -129,22 +129,22 @@ public class Controller implements Nameable
}
}
public static @NotNull Optional<Controller> by_guid(@NotNull String guid)
public static @NotNull Optional<Controller> byGuid(@NotNull String guid)
{
return CONTROLLERS.values().stream().filter(Controller::is_connected)
.filter(controller -> controller.get_guid().equals(guid))
.max(Comparator.comparingInt(Controller::get_id));
return CONTROLLERS.values().stream().filter(Controller::isConnected)
.filter(controller -> controller.getGuid().equals(guid))
.max(Comparator.comparingInt(Controller::getId));
}
/**
* Reads the specified resource and returns the raw data as a ByteBuffer.
*
* @param resource The resource to read.
* @param buffer_size The initial buffer size.
* @param resource The resource to read.
* @param bufferSize The initial buffer size.
* @return The resource data.
* @throws IOException If an IO error occurs.
*/
private static ByteBuffer io_resource_to_buffer(String resource, int buffer_size) throws IOException
private static ByteBuffer ioResourceToBuffer(String resource, int bufferSize) throws IOException
{
ByteBuffer buffer = null;
@@ -164,14 +164,14 @@ public class Controller implements Nameable
/**
* Updates the controller mappings.
*/
public static void update_mappings()
public static void updateMappings()
{
try {
File mappings_file = new File("config/gamecontrollerdb.txt");
if (!mappings_file.exists())
File mappingsFile = new File("config/gamecontrollerdb.txt");
if (!mappingsFile.exists())
return;
LambdaControlsClient.get().log("Updating controller mappings...");
ByteBuffer buffer = io_resource_to_buffer(mappings_file.getPath(), 1024);
ByteBuffer buffer = ioResourceToBuffer(mappingsFile.getPath(), 1024);
GLFW.glfwUpdateGamepadMappings(buffer);
} catch (IOException e) {
e.printStackTrace();

View File

@@ -10,15 +10,27 @@
package me.lambdaurora.lambdacontrols.client.controller;
import me.lambdaurora.lambdacontrols.client.ButtonState;
import me.lambdaurora.lambdacontrols.client.mixin.AdvancementsScreenAccessor;
import me.lambdaurora.lambdacontrols.client.mixin.CreativeInventoryScreenAccessor;
import me.lambdaurora.lambdacontrols.client.util.ContainerScreenAccessor;
import me.lambdaurora.lambdacontrols.client.util.KeyBindingAccessor;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.ingame.AbstractContainerScreen;
import net.minecraft.client.gui.screen.advancement.AdvancementTab;
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.util.ScreenshotUtils;
import net.minecraft.container.Slot;
import net.minecraft.item.ItemGroup;
import org.aperlambda.lambdacommon.utils.Pair;
import org.jetbrains.annotations.NotNull;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.function.Predicate;
import java.util.stream.Collectors;
/**
* Represents some input handlers.
*
@@ -28,13 +40,11 @@ import org.jetbrains.annotations.NotNull;
*/
public class InputHandlers
{
private static int hotbar_cooldown = 0;
private InputHandlers()
{
}
public static PressAction handle_hotbar(boolean right)
public static PressAction handleHotbar(boolean right)
{
return (client, button, action) -> {
if (action == ButtonState.RELEASE)
@@ -48,27 +58,42 @@ public class InputHandlers
client.player.inventory.selectedSlot = client.player.inventory.selectedSlot == 0 ? 8 : client.player.inventory.selectedSlot - 1;
return true;
} else if (client.currentScreen instanceof CreativeInventoryScreen) {
CreativeInventoryScreenAccessor creative_inventory = (CreativeInventoryScreenAccessor) client.currentScreen;
int current_selected_tab = creative_inventory.lambdacontrols_get_selected_tab();
int next_tab = current_selected_tab + (right ? 1 : -1);
if (next_tab < 0)
next_tab = ItemGroup.GROUPS.length - 1;
else if (next_tab >= ItemGroup.GROUPS.length)
next_tab = 0;
creative_inventory.lambdacontrols_set_selected_tab(ItemGroup.GROUPS[next_tab]);
CreativeInventoryScreenAccessor inventory = (CreativeInventoryScreenAccessor) client.currentScreen;
int currentSelectedTab = inventory.lambdacontrols_getSelectedTab();
int nextTab = currentSelectedTab + (right ? 1 : -1);
if (nextTab < 0)
nextTab = ItemGroup.GROUPS.length - 1;
else if (nextTab >= ItemGroup.GROUPS.length)
nextTab = 0;
inventory.lambdacontrols_setSelectedTab(ItemGroup.GROUPS[nextTab]);
return true;
} else if (client.currentScreen instanceof AdvancementsScreen) {
AdvancementsScreenAccessor screen = (AdvancementsScreenAccessor) client.currentScreen;
List<AdvancementTab> tabs = screen.lambdacontrols_getTabs().values().stream().distinct().collect(Collectors.toList());
AdvancementTab tab = screen.lambdacontrols_getSelectedTab();
for (int i = 0; i < tabs.size(); i++) {
if (tabs.get(i).equals(tab)) {
int nextTab = i + (right ? 1 : -1);
if (nextTab < 0)
nextTab = tabs.size() - 1;
else if (nextTab >= tabs.size())
nextTab = 0;
screen.lambdacontrols_getAdvancementManager().selectTab(tabs.get(nextTab).getRoot(), true);
break;
}
}
}
return false;
};
}
public static boolean handle_pause_game(@NotNull MinecraftClient client, @NotNull ButtonBinding binding, @NotNull ButtonState action)
public static boolean handlePauseGame(@NotNull MinecraftClient client, @NotNull ButtonBinding binding, @NotNull ButtonState action)
{
if (action == ButtonState.PRESS) {
// If in game, then pause the game.
if (client.currentScreen == null)
client.openPauseMenu(false);
else if (client.currentScreen instanceof AbstractContainerScreen && client.player != null) // If the current screen is a container then close it.
else if (client.currentScreen instanceof ContainerScreen && client.player != null) // If the current screen is a container then close it.
client.player.closeContainer();
else // Else just close the current screen.
client.currentScreen.onClose();
@@ -84,7 +109,7 @@ public class InputHandlers
* @param action The action done on the binding.
* @return True if handled, else false.
*/
public static boolean handle_screenshot(@NotNull MinecraftClient client, @NotNull ButtonBinding binding, @NotNull ButtonState action)
public static boolean handleScreenshot(@NotNull MinecraftClient client, @NotNull ButtonBinding binding, @NotNull ButtonState action)
{
if (action == ButtonState.PRESS)
ScreenshotUtils.saveScreenshot(client.runDirectory, client.getWindow().getFramebufferWidth(), client.getWindow().getFramebufferHeight(), client.getFramebuffer(),
@@ -92,12 +117,129 @@ public class InputHandlers
return true;
}
public static boolean handle_toggle_sneak(@NotNull MinecraftClient client, @NotNull ButtonBinding button, @NotNull ButtonState action)
public static boolean handleToggleSneak(@NotNull MinecraftClient client, @NotNull ButtonBinding button, @NotNull ButtonState action)
{
if (client.player != null && !client.player.abilities.flying) {
button.as_key_binding().filter(binding -> action == ButtonState.PRESS).ifPresent(binding -> ((KeyBindingAccessor) binding).handle_press_state(!binding.isPressed()));
button.asKeyBinding().filter(binding -> action == ButtonState.PRESS).ifPresent(binding -> ((KeyBindingAccessor) binding).lambdacontrols_handlePressState(!binding.isPressed()));
return true;
}
return false;
}
public static PressAction handleInventorySlotPad(int direction)
{
return (client, binding, action) -> {
if (!(client.currentScreen instanceof ContainerScreen && action != ButtonState.RELEASE))
return false;
ContainerScreen inventory = (ContainerScreen) client.currentScreen;
ContainerScreenAccessor accessor = (ContainerScreenAccessor) inventory;
int guiLeft = accessor.lambdacontrols_getX();
int guiTop = accessor.lambdacontrols_getY();
double mouseX = client.mouse.getX() * (double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth();
double mouseY = client.mouse.getY() * (double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight();
// Finds the hovered slot.
Slot mouseSlot = accessor.lambdacontrols_getSlotAt(mouseX, mouseY);
// Finds the closest slot in the GUI within 14 pixels.
Optional<Slot> closestSlot = inventory.getContainer().slots.parallelStream()
.filter(Predicate.isEqual(mouseSlot).negate())
.map(slot -> {
int posX = guiLeft + slot.xPosition + 8;
int posY = guiTop + slot.yPosition + 8;
int otherPosX = (int) mouseX;
int otherPosY = (int) mouseY;
if (mouseSlot != null) {
otherPosX = guiLeft + mouseSlot.xPosition + 8;
otherPosY = guiTop + mouseSlot.yPosition + 8;
}
// Distance between the slot and the cursor.
double distance = Math.sqrt(Math.pow(posX - otherPosX, 2) + Math.pow(posY - otherPosY, 2));
return Pair.of(slot, distance);
}).filter(entry -> {
Slot slot = entry.key;
int posX = guiLeft + slot.xPosition + 8;
int posY = guiTop + slot.yPosition + 8;
int otherPosX = (int) mouseX;
int otherPosY = (int) mouseY;
if (mouseSlot != null) {
otherPosX = guiLeft + mouseSlot.xPosition + 8;
otherPosY = guiTop + mouseSlot.yPosition + 8;
}
if (direction == 0)
return posY < otherPosY;
else if (direction == 1)
return posY > otherPosY;
else if (direction == 2)
return posX > otherPosX;
else if (direction == 3)
return posX < otherPosX;
else
return false;
})
.min(Comparator.comparingDouble(p -> p.value))
.map(p -> p.key);
if (closestSlot.isPresent()) {
Slot slot = closestSlot.get();
int x = guiLeft + slot.xPosition + 8;
int y = guiTop + slot.yPosition + 8;
InputManager.queueMousePosition(x * (double) client.getWindow().getWidth() / (double) client.getWindow().getScaledWidth(),
y * (double) client.getWindow().getHeight() / (double) client.getWindow().getScaledHeight());
return true;
}
return false;
};
}
/**
* Returns always true to the filter.
*
* @param client The client instance.
* @param binding The affected binding.
* @return True.
*/
public static boolean always(@NotNull MinecraftClient client, @NotNull ButtonBinding binding)
{
return true;
}
/**
* Returns whether the client is in game or not.
*
* @param client The client instance.
* @param binding The affected binding.
* @return True if the client is in game, else false.
*/
public static boolean inGame(@NotNull MinecraftClient client, @NotNull ButtonBinding binding)
{
return client.currentScreen == null;
}
/**
* Returns whether the client is in an inventory or not.
*
* @param client The client instance.
* @param binding The affected binding.
* @return True if the client is in an inventory, else false.
*/
public static boolean inInventory(@NotNull MinecraftClient client, @NotNull ButtonBinding binding)
{
return client.currentScreen instanceof ContainerScreen;
}
/**
* Returns whether the client is in the advancements screen or not.
*
* @param client The client instance.
* @param binding The affected binding.
* @return True if the client is in the advancements screen, else false.
*/
public static boolean inAdvancements(@NotNull MinecraftClient client, @NotNull ButtonBinding binding)
{
return client.currentScreen instanceof AdvancementsScreen;
}
}

View File

@@ -9,11 +9,17 @@
package me.lambdaurora.lambdacontrols.client.controller;
import me.lambdaurora.lambdacontrols.ControlsMode;
import me.lambdaurora.lambdacontrols.client.ButtonState;
import me.lambdaurora.lambdacontrols.client.LambdaControlsClient;
import me.lambdaurora.lambdacontrols.client.LambdaControlsConfig;
import me.lambdaurora.lambdacontrols.client.util.MouseAccessor;
import net.minecraft.client.MinecraftClient;
import net.minecraft.util.math.MathHelper;
import org.aperlambda.lambdacommon.Identifier;
import org.aperlambda.lambdacommon.utils.function.PairPredicate;
import org.jetbrains.annotations.NotNull;
import org.lwjgl.glfw.GLFW;
import java.util.*;
import java.util.function.Consumer;
@@ -29,9 +35,67 @@ import java.util.stream.Stream;
*/
public class InputManager
{
private static final List<ButtonBinding> BINDINGS = new ArrayList<>();
private static final List<ButtonCategory> CATEGORIES = new ArrayList<>();
public static final Map<Integer, ButtonState> STATES = new HashMap<>();
public static final InputManager INPUT_MANAGER = new InputManager();
private static final List<ButtonBinding> BINDINGS = new ArrayList<>();
private static final List<ButtonCategory> CATEGORIES = new ArrayList<>();
public static final Map<Integer, ButtonState> STATES = new HashMap<>();
private int prevTargetMouseX = 0;
private int prevTargetMouseY = 0;
private int targetMouseX = 0;
private int targetMouseY = 0;
protected InputManager()
{
}
public void tick(@NotNull MinecraftClient client)
{
if (LambdaControlsClient.get().config.getControlsMode() == ControlsMode.CONTROLLER) {
this.controllerTick(client);
}
}
public void controllerTick(@NotNull MinecraftClient client)
{
this.prevTargetMouseX = this.targetMouseX;
this.prevTargetMouseY = this.targetMouseY;
}
/**
* Updates the mouse position. Should only be called on pre render of a screen.
*
* @param client The client instance.
*/
public void updateMousePosition(@NotNull MinecraftClient client)
{
Objects.requireNonNull(client, "Client instance cannot be null.");
if (this.prevTargetMouseX != this.targetMouseX || this.prevTargetMouseY != this.targetMouseY) {
double mouseX = this.prevTargetMouseX + (this.targetMouseX - this.prevTargetMouseX) * client.getTickDelta() + 0.5;
double mouseY = this.prevTargetMouseY + (this.targetMouseY - this.prevTargetMouseY) * client.getTickDelta() + 0.5;
GLFW.glfwSetCursorPos(client.getWindow().getHandle(), mouseX, mouseY);
((MouseAccessor) client.mouse).lambdacontrols_onCursorPos(client.getWindow().getHandle(), mouseX, mouseY);
}
}
/**
* Resets the mouse position.
*
* @param windowWidth The window width.
* @param windowHeight The window height.
*/
public void resetMousePosition(int windowWidth, int windowHeight)
{
this.targetMouseX = this.prevTargetMouseX = (int) (windowWidth / 2.F);
this.targetMouseY = this.prevTargetMouseY = (int) (windowHeight / 2.F);
}
public void resetMouseTarget(@NotNull MinecraftClient client)
{
double mouseX = client.mouse.getX();
double mouseY = client.mouse.getY();
this.prevTargetMouseX = this.targetMouseX = (int) mouseX;
this.prevTargetMouseY = this.targetMouseY = (int) mouseY;
}
/**
* Returns whether the specified binding is registered or not.
@@ -39,7 +103,7 @@ public class InputManager
* @param binding The binding to check.
* @return True if the binding is registered, else false.
*/
public static boolean has_binding(@NotNull ButtonBinding binding)
public static boolean hasBinding(@NotNull ButtonBinding binding)
{
return BINDINGS.contains(binding);
}
@@ -50,9 +114,9 @@ public class InputManager
* @param name The name of the binding to check.
* @return True if the binding is registered, else false.
*/
public static boolean has_binding(@NotNull String name)
public static boolean hasBinding(@NotNull String name)
{
return BINDINGS.parallelStream().map(ButtonBinding::get_name).anyMatch(binding -> binding.equalsIgnoreCase(name));
return BINDINGS.parallelStream().map(ButtonBinding::getName).anyMatch(binding -> binding.equalsIgnoreCase(name));
}
/**
@@ -61,9 +125,9 @@ public class InputManager
* @param identifier The identifier of the binding to check.
* @return True if the binding is registered, else false.
*/
public static boolean has_binding(@NotNull Identifier identifier)
public static boolean hasBinding(@NotNull Identifier identifier)
{
return has_binding(identifier.get_namespace() + "." + identifier.get_name());
return hasBinding(identifier.getNamespace() + "." + identifier.getName());
}
/**
@@ -72,44 +136,44 @@ public class InputManager
* @param binding The binding to register.
* @return The registered binding.
*/
public static @NotNull ButtonBinding register_binding(@NotNull ButtonBinding binding)
public static @NotNull ButtonBinding registerBinding(@NotNull ButtonBinding binding)
{
if (has_binding(binding))
if (hasBinding(binding))
throw new IllegalStateException("Cannot register twice a button binding in the registry.");
BINDINGS.add(binding);
return binding;
}
public static @NotNull ButtonBinding register_binding(@NotNull Identifier binding_id, int[] default_button, @NotNull List<PressAction> actions, boolean has_cooldown)
public static @NotNull ButtonBinding registerBinding(@NotNull Identifier id, int[] defaultButton, @NotNull List<PressAction> actions, @NotNull PairPredicate<MinecraftClient, ButtonBinding> filter, boolean hasCooldown)
{
return register_binding(new ButtonBinding(binding_id.get_namespace() + "." + binding_id.get_name(), default_button, actions, has_cooldown));
return registerBinding(new ButtonBinding(id.getNamespace() + "." + id.getName(), defaultButton, actions, filter, hasCooldown));
}
public static @NotNull ButtonBinding register_binding(@NotNull Identifier binding_id, int[] default_button, boolean has_cooldown)
public static @NotNull ButtonBinding registerBinding(@NotNull Identifier id, int[] defaultButton, boolean hasCooldown)
{
return register_binding(binding_id, default_button, Collections.emptyList(), has_cooldown);
return registerBinding(id, defaultButton, Collections.emptyList(), InputHandlers::always, hasCooldown);
}
public static @NotNull ButtonBinding register_binding(@NotNull net.minecraft.util.Identifier binding_id, int[] default_button, @NotNull List<PressAction> actions, boolean has_cooldown)
public static @NotNull ButtonBinding registerBinding(@NotNull net.minecraft.util.Identifier id, int[] defaultButton, @NotNull List<PressAction> actions, @NotNull PairPredicate<MinecraftClient, ButtonBinding> filter, boolean hasCooldown)
{
return register_binding(new Identifier(binding_id.getNamespace(), binding_id.getPath()), default_button, actions, has_cooldown);
return registerBinding(new Identifier(id.getNamespace(), id.getPath()), defaultButton, actions, filter, hasCooldown);
}
public static @NotNull ButtonBinding register_binding(@NotNull net.minecraft.util.Identifier binding_id, int[] default_button, boolean has_cooldown)
public static @NotNull ButtonBinding registerBinding(@NotNull net.minecraft.util.Identifier id, int[] defaultButton, boolean hasCooldown)
{
return register_binding(binding_id, default_button, Collections.emptyList(), has_cooldown);
return registerBinding(id, defaultButton, Collections.emptyList(), InputHandlers::always, hasCooldown);
}
/**
* Sorts bindings to get bindings with the higher button counts first.
*/
public static void sort_bindings()
public static void sortBindings()
{
synchronized (BINDINGS) {
List<ButtonBinding> sorted_bindings = BINDINGS.stream().sorted(Collections.reverseOrder(Comparator.comparingInt(binding -> binding.get_button().length)))
List<ButtonBinding> sorted = BINDINGS.stream().sorted(Collections.reverseOrder(Comparator.comparingInt(binding -> binding.getButton().length)))
.collect(Collectors.toList());
BINDINGS.clear();
BINDINGS.addAll(sorted_bindings);
BINDINGS.addAll(sorted);
}
}
@@ -119,26 +183,26 @@ public class InputManager
* @param category The category to register.
* @return The registered category.
*/
public static ButtonCategory register_category(@NotNull ButtonCategory category)
public static ButtonCategory registerCategory(@NotNull ButtonCategory category)
{
CATEGORIES.add(category);
return category;
}
public static ButtonCategory register_category(@NotNull Identifier identifier, int priority)
public static ButtonCategory registerCategory(@NotNull Identifier identifier, int priority)
{
return register_category(new ButtonCategory(identifier, priority));
return registerCategory(new ButtonCategory(identifier, priority));
}
public static ButtonCategory register_category(@NotNull Identifier identifier)
public static ButtonCategory registerCategory(@NotNull Identifier identifier)
{
return register_category(new ButtonCategory(identifier));
return registerCategory(new ButtonCategory(identifier));
}
protected static ButtonCategory register_default_category(@NotNull String key, @NotNull Consumer<ButtonCategory> key_adder)
protected static ButtonCategory registerDefaultCategory(@NotNull String key, @NotNull Consumer<ButtonCategory> keyAdder)
{
ButtonCategory category = register_category(new Identifier("minecraft", key), CATEGORIES.size());
key_adder.accept(category);
ButtonCategory category = registerCategory(new Identifier("minecraft", key), CATEGORIES.size());
keyAdder.accept(category);
return category;
}
@@ -147,10 +211,10 @@ public class InputManager
*
* @param config The configuration instance.
*/
public static void load_button_bindings(@NotNull LambdaControlsConfig config)
public static void loadButtonBindings(@NotNull LambdaControlsConfig config)
{
List<ButtonBinding> load_queue = new ArrayList<>(BINDINGS);
load_queue.forEach(config::load_button_binding);
List<ButtonBinding> queue = new ArrayList<>(BINDINGS);
queue.forEach(config::loadButtonBinding);
}
/**
@@ -159,17 +223,17 @@ public class InputManager
* @param binding The binding.
* @return The current state of the binding.
*/
public static @NotNull ButtonState get_binding_state(@NotNull ButtonBinding binding)
public static @NotNull ButtonState getBindingState(@NotNull ButtonBinding binding)
{
ButtonState state = ButtonState.REPEAT;
for (int btn : binding.get_button()) {
ButtonState btn_state = InputManager.STATES.getOrDefault(btn, ButtonState.NONE);
if (btn_state == ButtonState.PRESS)
for (int btn : binding.getButton()) {
ButtonState btnState = InputManager.STATES.getOrDefault(btn, ButtonState.NONE);
if (btnState == ButtonState.PRESS)
state = ButtonState.PRESS;
else if (btn_state == ButtonState.RELEASE) {
else if (btnState == ButtonState.RELEASE) {
state = ButtonState.RELEASE;
break;
} else if (btn_state == ButtonState.NONE) {
} else if (btnState == ButtonState.NONE) {
state = ButtonState.NONE;
break;
}
@@ -183,9 +247,20 @@ public class InputManager
* @param button The button to check.
* @return True if the button has duplicated bindings, else false.
*/
public static boolean has_duplicated_bindings(int[] button)
public static boolean hasDuplicatedBindings(int[] button)
{
return BINDINGS.parallelStream().filter(binding -> are_buttons_equivalent(binding.get_button(), button)).count() > 1;
return BINDINGS.parallelStream().filter(binding -> areButtonsEquivalent(binding.getButton(), button)).count() > 1;
}
/**
* Returns whether the button has duplicated bindings.
*
* @param binding The binding to check.
* @return True if the button has duplicated bindings, else false.
*/
public static boolean hasDuplicatedBindings(ButtonBinding binding)
{
return BINDINGS.parallelStream().filter(other -> areButtonsEquivalent(other.getButton(), binding.getButton()) && other.filter.equals(binding.filter)).count() > 1;
}
/**
@@ -195,7 +270,7 @@ public class InputManager
* @param buttons2 Second set of buttons.
* @return True if the two sets of buttons are equivalent, else false.
*/
public static boolean are_buttons_equivalent(int[] buttons1, int[] buttons2)
public static boolean areButtonsEquivalent(int[] buttons1, int[] buttons2)
{
if (buttons1.length != buttons2.length)
return false;
@@ -218,7 +293,7 @@ public class InputManager
* @param button The button to check.
* @return True if the button set contains the specified button, else false.
*/
public static boolean contains_button(int[] buttons, int button)
public static boolean containsButton(int[] buttons, int button)
{
return Arrays.stream(buttons).anyMatch(btn -> btn == button);
}
@@ -226,7 +301,7 @@ public class InputManager
/**
* Updates the button states.
*/
public static void update_states()
public static void updateStates()
{
STATES.forEach((btn, state) -> {
if (state == ButtonState.PRESS)
@@ -236,37 +311,49 @@ public class InputManager
});
}
public static void update_bindings(@NotNull MinecraftClient client)
public static void updateBindings(@NotNull MinecraftClient client)
{
List<Integer> skip_buttons = new ArrayList<>();
List<Integer> skipButtons = new ArrayList<>();
Map<ButtonBinding, ButtonState> states = new HashMap<>();
for (ButtonBinding binding : BINDINGS) {
ButtonState binding_state = get_binding_state(binding);
if (skip_buttons.stream().anyMatch(btn -> contains_button(binding.get_button(), btn))) {
ButtonState state = binding.isAvailable(client) ? getBindingState(binding) : ButtonState.NONE;
if (skipButtons.stream().anyMatch(btn -> containsButton(binding.getButton(), btn))) {
if (binding.pressed)
binding_state = ButtonState.RELEASE;
state = ButtonState.RELEASE;
else
binding_state = ButtonState.NONE;
state = ButtonState.NONE;
}
binding.pressed = binding_state.is_pressed();
binding.pressed = state.isPressed();
binding.update();
if (binding.pressed)
Arrays.stream(binding.get_button()).forEach(skip_buttons::add);
states.put(binding, binding_state);
Arrays.stream(binding.getButton()).forEach(skipButtons::add);
states.put(binding, state);
}
states.forEach((binding, state) -> {
if (state != ButtonState.NONE)
if (state != ButtonState.NONE) {
binding.handle(client, state);
}
});
}
public static @NotNull Stream<ButtonBinding> stream_bindings()
public static void queueMousePosition(double x, double y)
{
INPUT_MANAGER.targetMouseX = (int) MathHelper.clamp(x, 0, MinecraftClient.getInstance().getWindow().getWidth());
INPUT_MANAGER.targetMouseY = (int) MathHelper.clamp(y, 0, MinecraftClient.getInstance().getWindow().getHeight());
}
public static void queueMoveMousePosition(double x, double y)
{
queueMousePosition(INPUT_MANAGER.targetMouseX + x, INPUT_MANAGER.targetMouseY + y);
}
public static @NotNull Stream<ButtonBinding> streamBindings()
{
return BINDINGS.stream();
}
public static @NotNull Stream<ButtonCategory> stream_categories()
public static @NotNull Stream<ButtonCategory> streamCategories()
{
return CATEGORIES.stream();
}

View File

@@ -27,7 +27,7 @@ public interface PressAction
PressAction DEFAULT_ACTION = (client, button, action) -> {
if (action == ButtonState.REPEAT || client.currentScreen != null)
return false;
button.as_key_binding().ifPresent(key_binding -> ((KeyBindingAccessor) key_binding).handle_press_state(button.is_button_down()));
button.asKeyBinding().ifPresent(binding -> ((KeyBindingAccessor) binding).lambdacontrols_handlePressState(button.isButtonDown()));
return true;
};

View File

@@ -23,37 +23,37 @@ import org.jetbrains.annotations.NotNull;
public class ControllerButtonWidget extends AbstractIconButtonWidget
{
private ButtonBinding binding;
private int icon_width;
private int iconWidth;
public ControllerButtonWidget(int x, int y, int width, @NotNull ButtonBinding button_binding, @NotNull PressAction on_press)
public ControllerButtonWidget(int x, int y, int width, @NotNull ButtonBinding binding, @NotNull PressAction action)
{
super(x, y, width, 20, ButtonBinding.get_localized_button_name(button_binding.get_button()[0]), on_press);
this.binding = button_binding;
super(x, y, width, 20, ButtonBinding.getLocalizedButtonName(binding.getButton()[0]), action);
this.binding = binding;
}
public void update()
{
int length = binding.get_button().length;
this.setMessage(this.binding.is_not_bound() ? I18n.translate("lambdacontrols.not_bound") :
(length > 0 ? ButtonBinding.get_localized_button_name(binding.get_button()[0]) : "<>"));
int length = binding.getButton().length;
this.setMessage(this.binding.isNotBound() ? I18n.translate("lambdacontrols.not_bound") :
(length > 0 ? ButtonBinding.getLocalizedButtonName(binding.getButton()[0]) : "<>"));
}
@Override
public String getMessage()
{
if (this.binding.get_button().length > 1)
if (this.binding.getButton().length > 1)
return "";
return super.getMessage();
}
@Override
protected int render_icon(int mouse_x, int mouse_y, float delta, int x, int y)
protected int renderIcon(int mouseX, int mouseY, float delta, int x, int y)
{
if (this.binding.get_button().length > 1) {
x += (this.width / 2 - this.icon_width / 2) - 4;
if (this.binding.getButton().length > 1) {
x += (this.width / 2 - this.iconWidth / 2) - 4;
}
Pair<Integer, Integer> size = LambdaControlsClient.draw_button(x, y, this.binding, MinecraftClient.getInstance());
this.icon_width = size.get_key();
return size.get_value();
Pair<Integer, Integer> size = LambdaControlsClient.drawButton(x, y, this.binding, MinecraftClient.getInstance());
this.iconWidth = size.key;
return size.value;
}
}

View File

@@ -18,33 +18,32 @@ import net.minecraft.client.gui.screen.options.ControlsOptionsScreen;
import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.client.resource.language.I18n;
import net.minecraft.text.TranslatableText;
import org.aperlambda.lambdacommon.utils.function.Predicates;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.function.Predicate;
/**
* Represents the controls screen.
*/
public class LambdaControlsControlsScreen extends Screen
public class ControllerControlsScreen extends Screen
{
private final Screen parent;
final LambdaControlsClient mod;
private final boolean hide_settings;
private ControlsListWidget bindings_list_widget;
private ButtonWidget reset_button;
public ButtonBinding focused_binding;
public boolean waiting = false;
public List<Integer> current_buttons = new ArrayList<>();
private final boolean hideSettings;
private ControlsListWidget bindingsListWidget;
private ButtonWidget resetButton;
public ButtonBinding focusedBinding;
public boolean waiting = false;
public List<Integer> currentButtons = new ArrayList<>();
public LambdaControlsControlsScreen(@NotNull Screen parent, boolean hide_settings)
public ControllerControlsScreen(@NotNull Screen parent, boolean hideSettings)
{
super(new TranslatableText("lambdacontrols.menu.title.controller_controls"));
this.parent = parent;
this.mod = LambdaControlsClient.get();
this.hide_settings = hide_settings;
this.hideSettings = hideSettings;
}
@Override
@@ -57,33 +56,26 @@ public class LambdaControlsControlsScreen extends Screen
@Override
protected void init()
{
this.addButton(new SpruceButtonWidget(this.width / 2 - 155, 18, this.hide_settings ? 310 : 150, 20, I18n.translate("lambdacontrols.menu.keyboard_controls"),
this.addButton(new SpruceButtonWidget(this.width / 2 - 155, 18, this.hideSettings ? 310 : 150, 20, I18n.translate("lambdacontrols.menu.keyboard_controls"),
btn -> this.minecraft.openScreen(new ControlsOptionsScreen(this, this.minecraft.options))));
if (!this.hide_settings)
if (!this.hideSettings)
this.addButton(new SpruceButtonWidget(this.width / 2 - 155 + 160, 18, 150, 20, I18n.translate("menu.options"),
btn -> this.minecraft.openScreen(new LambdaControlsSettingsScreen(this, this.minecraft.options, true))));
this.bindings_list_widget = new ControlsListWidget(this, this.minecraft);
this.children.add(this.bindings_list_widget);
this.reset_button = this.addButton(new ButtonWidget(this.width / 2 - 155, this.height - 29, 150, 20, I18n.translate("controls.resetAll"),
btn -> InputManager.stream_bindings().forEach(binding -> this.mod.config.set_button_binding(binding, binding.get_default_button()))));
this.bindingsListWidget = new ControlsListWidget(this, this.minecraft);
this.children.add(this.bindingsListWidget);
this.resetButton = this.addButton(new ButtonWidget(this.width / 2 - 155, this.height - 29, 150, 20, I18n.translate("controls.resetAll"),
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"),
btn -> this.minecraft.openScreen(this.parent)));
}
// Replacement for Predicate#not as it is Java 11.
private <T> Predicate<T> not(Predicate<T> target)
{
Objects.requireNonNull(target);
return target.negate();
}
@Override
public void render(int mouse_x, int mouse_y, float delta)
public void render(int mouseX, int mouseY, float delta)
{
this.renderBackground();
this.bindings_list_widget.render(mouse_x, mouse_y, delta);
this.bindingsListWidget.render(mouseX, mouseY, delta);
this.drawCenteredString(this.font, this.title.asFormattedString(), this.width / 2, 8, 16777215);
this.reset_button.active = InputManager.stream_bindings().anyMatch(this.not(ButtonBinding::is_default));
super.render(mouse_x, mouse_y, delta);
this.resetButton.active = InputManager.streamBindings().anyMatch(Predicates.not(ButtonBinding::isDefault));
super.render(mouseX, mouseY, delta);
}
}

View File

@@ -33,22 +33,22 @@ import java.util.List;
*/
public class ControlsListWidget extends ElementListWidget<ControlsListWidget.Entry>
{
private static final int[] UNBOUND = new int[0];
private final LambdaControlsControlsScreen gui;
private int field_2733;
private static final int[] UNBOUND = new int[0];
private final ControllerControlsScreen gui;
private int field_2733;
public ControlsListWidget(@NotNull LambdaControlsControlsScreen gui, @NotNull MinecraftClient client)
public ControlsListWidget(@NotNull ControllerControlsScreen gui, @NotNull MinecraftClient client)
{
super(client, gui.width + 45, gui.height, 43, gui.height - 32, 24);
this.gui = gui;
InputManager.stream_categories()
.sorted(Comparator.comparingInt(ButtonCategory::get_priority))
InputManager.streamCategories()
.sorted(Comparator.comparingInt(ButtonCategory::getPriority))
.forEach(category -> {
this.addEntry(new CategoryEntry(category));
category.get_bindings().forEach(binding -> {
int i = client.textRenderer.getStringWidth(I18n.translate(binding.get_translation_key()));
category.getBindings().forEach(binding -> {
int i = client.textRenderer.getStringWidth(I18n.translate(binding.getTranslationKey()));
if (i > this.field_2733) {
this.field_2733 = i;
}
@@ -73,43 +73,43 @@ public class ControlsListWidget extends ElementListWidget<ControlsListWidget.Ent
public class ButtonBindingEntry extends Entry
{
private final ButtonBinding binding;
private final String binding_name;
private final ControllerButtonWidget edit_button;
private final ButtonWidget reset_button;
private final ButtonWidget unbound_button;
private final String bindingName;
private final ControllerButtonWidget editButton;
private final ButtonWidget resetButton;
private final ButtonWidget unboundButton;
ButtonBindingEntry(@NotNull ButtonBinding binding)
{
this.binding = binding;
this.binding_name = I18n.translate(this.binding.get_translation_key());
this.edit_button = new ControllerButtonWidget(0, 0, 110, this.binding, btn -> {
gui.focused_binding = binding;
gui.current_buttons.clear();
this.bindingName = I18n.translate(this.binding.getTranslationKey());
this.editButton = new ControllerButtonWidget(0, 0, 110, this.binding, btn -> {
gui.focusedBinding = binding;
gui.currentButtons.clear();
gui.waiting = true;
})
{
protected String getNarrationMessage()
{
return binding.is_not_bound() ? I18n.translate("narrator.controls.unbound", binding_name) : I18n.translate("narrator.controls.bound", binding_name, super.getNarrationMessage());
return binding.isNotBound() ? I18n.translate("narrator.controls.unbound", bindingName) : I18n.translate("narrator.controls.bound", bindingName, super.getNarrationMessage());
}
};
this.reset_button = new ButtonWidget(0, 0, 50, 20, I18n.translate("controls.reset"),
btn -> gui.mod.config.set_button_binding(binding, binding.get_default_button()))
this.resetButton = new ButtonWidget(0, 0, 50, 20, I18n.translate("controls.reset"),
btn -> gui.mod.config.setButtonBinding(binding, binding.getDefaultButton()))
{
protected String getNarrationMessage()
{
return I18n.translate("narrator.controls.reset", binding_name);
return I18n.translate("narrator.controls.reset", bindingName);
}
};
this.unbound_button = new ButtonWidget(0, 0, 50, 20, I18n.translate("lambdacontrols.menu.unbound"),
this.unboundButton = new ButtonWidget(0, 0, 50, 20, I18n.translate("lambdacontrols.menu.unbound"),
btn -> {
gui.mod.config.set_button_binding(binding, UNBOUND);
gui.focused_binding = null;
gui.mod.config.setButtonBinding(binding, UNBOUND);
gui.focusedBinding = null;
})
{
protected String getNarrationMessage()
{
return I18n.translate("lambdacontrols.narrator.unbound", binding_name);
return I18n.translate("lambdacontrols.narrator.unbound", bindingName);
}
};
}
@@ -117,71 +117,71 @@ public class ControlsListWidget extends ElementListWidget<ControlsListWidget.Ent
@Override
public List<? extends Element> children()
{
return Collections.unmodifiableList(Arrays.asList(this.edit_button, this.reset_button));
return Collections.unmodifiableList(Arrays.asList(this.editButton, this.resetButton));
}
@Override
public void render(int index, int y, int x, int width, int height, int mouse_x, int mouse_y, boolean hovering, float delta)
public void render(int index, int y, int x, int width, int height, int mouseX, int mouseY, boolean hovering, float delta)
{
boolean focused = gui.focused_binding == this.binding;
TextRenderer text_renderer = ControlsListWidget.this.minecraft.textRenderer;
String binding_name = this.binding_name;
boolean focused = gui.focusedBinding == this.binding;
TextRenderer textRenderer = ControlsListWidget.this.minecraft.textRenderer;
String bindingName = this.bindingName;
float var10002 = (float) (x + 70 - ControlsListWidget.this.field_2733);
int var10003 = y + height / 2;
text_renderer.draw(binding_name, var10002, (float) (var10003 - 9 / 2), 16777215);
this.reset_button.x = this.unbound_button.x = x + 190;
this.reset_button.y = this.unbound_button.y = y;
this.reset_button.active = !this.binding.is_default();
textRenderer.draw(bindingName, var10002, (float) (var10003 - 9 / 2), 16777215);
this.resetButton.x = this.unboundButton.x = x + 190;
this.resetButton.y = this.unboundButton.y = y;
this.resetButton.active = !this.binding.isDefault();
if (focused)
this.unbound_button.render(mouse_x, mouse_y, delta);
this.unboundButton.render(mouseX, mouseY, delta);
else
this.reset_button.render(mouse_x, mouse_y, delta);
this.edit_button.x = x + 75;
this.edit_button.y = y;
this.edit_button.update();
this.resetButton.render(mouseX, mouseY, delta);
this.editButton.x = x + 75;
this.editButton.y = y;
this.editButton.update();
if (focused) {
this.edit_button.setMessage(Formatting.WHITE + "> " + Formatting.YELLOW + this.edit_button.getMessage() + Formatting.WHITE + " <");
} else if (!this.binding.is_not_bound() && InputManager.has_duplicated_bindings(this.binding.get_button())) {
this.edit_button.setMessage(Formatting.RED + this.edit_button.getMessage());
} else if (this.binding.is_not_bound()) {
this.edit_button.setMessage(Formatting.GOLD + this.edit_button.getMessage());
this.editButton.setMessage(Formatting.WHITE + "> " + Formatting.YELLOW + this.editButton.getMessage() + Formatting.WHITE + " <");
} else if (!this.binding.isNotBound() && InputManager.hasDuplicatedBindings(this.binding)) {
this.editButton.setMessage(Formatting.RED + this.editButton.getMessage());
} else if (this.binding.isNotBound()) {
this.editButton.setMessage(Formatting.GOLD + this.editButton.getMessage());
}
this.edit_button.render(mouse_x, mouse_y, delta);
this.editButton.render(mouseX, mouseY, delta);
}
public boolean mouseClicked(double mouse_x, double mouse_y, int button)
public boolean mouseClicked(double mouseX, double mouseY, int button)
{
boolean focused = gui.focused_binding == this.binding;
if (this.edit_button.mouseClicked(mouse_x, mouse_y, button))
boolean focused = gui.focusedBinding == this.binding;
if (this.editButton.mouseClicked(mouseX, mouseY, button))
return true;
else
return focused ? this.unbound_button.mouseClicked(mouse_x, mouse_y, button) : this.reset_button.mouseClicked(mouse_x, mouse_y, button);
return focused ? this.unboundButton.mouseClicked(mouseX, mouseY, button) : this.resetButton.mouseClicked(mouseX, mouseY, button);
}
public boolean mouseReleased(double mouse_x, double mouse_y, int button)
public boolean mouseReleased(double mouseX, double mouseY, int button)
{
return this.edit_button.mouseReleased(mouse_x, mouse_y, button) || this.reset_button.mouseReleased(mouse_x, mouse_y, button)
|| this.unbound_button.mouseReleased(mouse_x, mouse_y, button);
return this.editButton.mouseReleased(mouseX, mouseY, button) || this.resetButton.mouseReleased(mouseX, mouseY, button)
|| this.unboundButton.mouseReleased(mouseX, mouseY, button);
}
}
public class CategoryEntry extends Entry
{
private final String name;
private final int name_width;
private final int nameWidth;
public CategoryEntry(@NotNull ButtonCategory category)
{
this.name = category.get_translated_name();
this.name_width = ControlsListWidget.this.minecraft.textRenderer.getStringWidth(this.name);
this.name = category.getTranslatedName();
this.nameWidth = ControlsListWidget.this.minecraft.textRenderer.getStringWidth(this.name);
}
@Override
public void render(int index, int y, int x, int width, int height, int mouse_x, int mouse_y, boolean hovering, float delta)
public void render(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.name_width / 2),
ControlsListWidget.this.minecraft.textRenderer.draw(this.name, (float) (ControlsListWidget.this.minecraft.currentScreen.width / 2 - this.nameWidth / 2),
(float) ((y + height) - 9 - 1), 16777215);
}

View File

@@ -10,11 +10,13 @@
package me.lambdaurora.lambdacontrols.client.gui;
import me.lambdaurora.lambdacontrols.ControlsMode;
import me.lambdaurora.lambdacontrols.LambdaControlsConstants;
import me.lambdaurora.lambdacontrols.client.HudSide;
import me.lambdaurora.lambdacontrols.client.LambdaControlsClient;
import me.lambdaurora.lambdacontrols.client.controller.ButtonBinding;
import me.lambdaurora.spruceui.hud.Hud;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.DrawableHelper;
import net.minecraft.util.Identifier;
import net.minecraft.util.hit.HitResult;
import org.jetbrains.annotations.NotNull;
@@ -25,32 +27,39 @@ import org.jetbrains.annotations.NotNull;
* @version 1.1.0
* @since 1.0.0
*/
public class LambdaControlsHud extends DrawableHelper
public class LambdaControlsHud extends Hud
{
private final MinecraftClient client;
private final LambdaControlsClient mod;
private int width_bottom = 0;
private int width_top = 0;
private MinecraftClient client;
private int widthBottom = 0;
private int widthTop = 0;
public LambdaControlsHud(@NotNull MinecraftClient client, @NotNull LambdaControlsClient mod)
public LambdaControlsHud(@NotNull LambdaControlsClient mod)
{
this.client = client;
super(new Identifier(LambdaControlsConstants.NAMESPACE, "hud/button_indicator"));
this.mod = mod;
}
@Override
public void init(@NotNull MinecraftClient client, int screenWidth, int screenHeight)
{
super.init(client, screenWidth, screenHeight);
this.client = client;
}
/**
* Renders the LambdaControls' HUD.
*/
public void render()
public void render(float tickDelta)
{
if (this.mod.config.get_controls_mode() == ControlsMode.CONTROLLER && this.mod.config.is_hud_enabled() && this.client.currentScreen == null && !this.client.options.hudHidden) {
int x = this.mod.config.get_hud_side() == HudSide.LEFT ? 10 : client.getWindow().getScaledWidth() - 10 - this.width_bottom, y = bottom(10);
x += (this.width_bottom = this.draw_button_tip(x, y, ButtonBinding.INVENTORY, true) + 10);
this.width_bottom += this.draw_button_tip(x, y, ButtonBinding.SWAP_HANDS, true);
x = this.mod.config.get_hud_side() == HudSide.LEFT ? 10 : client.getWindow().getScaledWidth() - 10 - this.width_top;
x += (this.width_top = this.draw_button_tip(x, (y -= 20), ButtonBinding.DROP_ITEM, !this.client.player.getMainHandStack().isEmpty()) + 10);
this.width_top += this.draw_button_tip(x, y, ButtonBinding.ATTACK.get_button(),
this.client.crosshairTarget.getType() == HitResult.Type.BLOCK ? "lambdacontrols.action.hit" : ButtonBinding.ATTACK.get_translation_key(),
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);
x += (this.widthBottom = this.drawButtonTip(x, y, ButtonBinding.INVENTORY, true) + 10);
this.widthBottom += this.drawButtonTip(x, y, ButtonBinding.SWAP_HANDS, true);
x = this.mod.config.getHudSide() == HudSide.LEFT ? 10 : client.getWindow().getScaledWidth() - 10 - this.widthTop;
x += (this.widthTop = this.drawButtonTip(x, (y -= 20), ButtonBinding.DROP_ITEM, !this.client.player.getMainHandStack().isEmpty()) + 10);
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);
}
}
@@ -60,13 +69,13 @@ public class LambdaControlsHud extends DrawableHelper
return this.client.getWindow().getScaledHeight() - y - 15;
}
private int draw_button_tip(int x, int y, @NotNull ButtonBinding button, boolean display)
private int drawButtonTip(int x, int y, @NotNull ButtonBinding button, boolean display)
{
return LambdaControlsClient.draw_button_tip(x, y, button, display, this.client);
return LambdaControlsClient.drawButtonTip(x, y, button, display, this.client);
}
private int draw_button_tip(int x, int y, int[] button, @NotNull String action, boolean display)
private int drawButtonTip(int x, int y, int[] button, @NotNull String action, boolean display)
{
return LambdaControlsClient.draw_button_tip(x, y, button, action, display, this.client);
return LambdaControlsClient.drawButtonTip(x, y, button, action, display, this.client);
}
}

View File

@@ -10,18 +10,19 @@
package me.lambdaurora.lambdacontrols.client.gui;
import me.lambdaurora.lambdacontrols.ControlsMode;
import me.lambdaurora.lambdacontrols.LambdaControls;
import me.lambdaurora.lambdacontrols.client.LambdaControlsClient;
import me.lambdaurora.lambdacontrols.client.controller.Controller;
import me.lambdaurora.spruceui.SpruceButtonWidget;
import me.lambdaurora.spruceui.SpruceLabelWidget;
import me.lambdaurora.spruceui.Tooltip;
import me.lambdaurora.spruceui.option.*;
import net.fabricmc.fabric.api.network.ClientSidePacketRegistry;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.screen.options.ControlsOptionsScreen;
import net.minecraft.client.gui.widget.ButtonListWidget;
import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.client.options.CyclingOption;
import net.minecraft.client.options.GameOptions;
import net.minecraft.client.options.Option;
import net.minecraft.client.resource.language.I18n;
@@ -36,132 +37,135 @@ import org.lwjgl.glfw.GLFW;
*/
public class LambdaControlsSettingsScreen extends Screen
{
public static final String GAMEPAD_TOOL_URL = "http://generalarcade.com/gamepadtool/";
public static final String GAMEPAD_TOOL_URL = "http://generalarcade.com/gamepadtool/";
final LambdaControlsClient mod;
private final Screen parent;
private final boolean hide_controls;
private final boolean hideControls;
// General options
private final Option auto_switch_mode_option;
private final Option rotation_speed_option;
private final Option mouse_speed_option;
private final Option reset_option;
private final Option autoSwitchModeOption;
private final Option rotationSpeedOption;
private final Option mouseSpeedOption;
private final Option resetOption;
// Gameplay options
private final Option front_block_placing_option;
private final Option fly_drifting_option;
private final Option frontBlockPlacingOption;
private final Option flyDriftingOption;
private final Option flyVerticalDriftingOption;
// Controller options
private final Option controller_option;
private final Option second_controller_option;
private final Option controller_type_option;
private final Option dead_zone_option;
private final Option inverts_right_x_axis;
private final Option inverts_right_y_axis;
private final Option unfocused_input_option;
private final Option controllerOption;
private final Option secondControllerOption;
private final Option controllerTypeOption;
private final Option deadZoneOption;
private final Option invertsRightXAxis;
private final Option invertsRightYAxis;
private final Option unfocusedInputOption;
// Hud options
private final Option hud_enable_option;
private final Option hud_side_option;
private final String controller_mappings_url_text = I18n.translate("lambdacontrols.controller.mappings.2", Formatting.GOLD.toString(), GAMEPAD_TOOL_URL, Formatting.RESET.toString());
private final Option hudEnableOption;
private final Option hudSideOption;
private final String controllerMappingsUrlText = I18n.translate("lambdacontrols.controller.mappings.2", Formatting.GOLD.toString(), GAMEPAD_TOOL_URL, Formatting.RESET.toString());
private ButtonListWidget list;
private SpruceLabelWidget gamepad_tool_url_label;
private SpruceLabelWidget gamepadToolUrlLabel;
public LambdaControlsSettingsScreen(Screen parent, @NotNull GameOptions options, boolean hide_controls)
public LambdaControlsSettingsScreen(Screen parent, @NotNull GameOptions options, boolean hideControls)
{
super(new TranslatableText("lambdacontrols.title.settings"));
this.mod = LambdaControlsClient.get();
this.parent = parent;
this.hide_controls = hide_controls;
this.hideControls = hideControls;
// General options
this.auto_switch_mode_option = new SpruceBooleanOption("lambdacontrols.menu.auto_switch_mode", game_options -> this.mod.config.has_auto_switch_mode(),
(game_options, new_value) -> this.mod.config.set_auto_switch_mode(new_value), new TranslatableText("lambdacontrols.tooltip.auto_switch_mode"), true);
this.rotation_speed_option = new SpruceDoubleOption("lambdacontrols.menu.rotation_speed", 0.0, 150.0, 0.5F, game_options -> this.mod.config.get_rotation_speed(),
(game_options, new_value) -> {
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.rotationSpeedOption = new SpruceDoubleOption("lambdacontrols.menu.rotation_speed", 0.0, 150.0, 0.5F, this.mod.config::getRotationSpeed,
newValue -> {
synchronized (this.mod.config) {
this.mod.config.set_rotation_speed(new_value);
this.mod.config.setRotationSpeed(newValue);
}
}, (game_options, option) -> option.getDisplayPrefix() + option.get(options),
}, option -> option.getDisplayPrefix() + option.get(),
new TranslatableText("lambdacontrols.tooltip.rotation_speed"));
this.mouse_speed_option = new SpruceDoubleOption("lambdacontrols.menu.mouse_speed", 0.0, 150.0, 0.5F, game_options -> this.mod.config.get_mouse_speed(),
(game_options, new_value) -> {
this.mouseSpeedOption = new SpruceDoubleOption("lambdacontrols.menu.mouse_speed", 0.0, 150.0, 0.5F, this.mod.config::getMouseSpeed,
newValue -> {
synchronized (this.mod.config) {
this.mod.config.set_mouse_speed(new_value);
this.mod.config.setMouseSpeed(newValue);
}
}, (game_options, option) -> option.getDisplayPrefix() + option.get(options),
}, option -> option.getDisplayPrefix() + option.get(),
new TranslatableText("lambdacontrols.tooltip.mouse_speed"));
this.reset_option = new SpruceResetOption(btn -> {
this.resetOption = new SpruceResetOption(btn -> {
this.mod.config.reset();
MinecraftClient client = MinecraftClient.getInstance();
this.init(client, client.getWindow().getScaledWidth(), client.getWindow().getScaledHeight());
});
// Gameplay options
this.front_block_placing_option = new SpruceBooleanOption("lambdacontrols.menu.front_block_placing", game_options -> this.mod.config.has_front_block_placing(),
(game_options, new_value) -> this.mod.config.set_front_block_placing(new_value), new TranslatableText("lambdacontrols.tooltip.front_block_placing"), true);
this.fly_drifting_option = new SpruceBooleanOption("lambdacontrols.menu.fly_drifting", game_options -> this.mod.config.has_fly_drifting(),
(game_options, new_value) -> this.mod.config.set_fly_drifting(new_value), new TranslatableText("lambdacontrols.tooltip.fly_drifting"), true);
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.flyDriftingOption = new SpruceBooleanOption("lambdacontrols.menu.fly_drifting", this.mod.config::hasFlyDrifting,
this.mod.config::setFlyDrifting, new TranslatableText("lambdacontrols.tooltip.fly_drifting"), true);
this.flyVerticalDriftingOption = new SpruceBooleanOption("lambdacontrols.menu.fly_drifting_vertical", this.mod.config::hasFlyVerticalDrifting,
this.mod.config::setFlyVerticalDrifting, new TranslatableText("lambdacontrols.tooltip.fly_drifting_vertical"), true);
// Controller options
this.controller_option = new CyclingOption("lambdacontrols.menu.controller", (game_options, amount) -> {
int current_id = this.mod.config.get_controller().get_id();
current_id += amount;
if (current_id > GLFW.GLFW_JOYSTICK_LAST)
current_id = GLFW.GLFW_JOYSTICK_1;
this.mod.config.set_controller(Controller.by_id(current_id));
}, (game_options, option) -> {
String controller_name = this.mod.config.get_controller().get_name();
if (!this.mod.config.get_controller().is_connected())
return option.getDisplayPrefix() + Formatting.RED + controller_name;
else if (!this.mod.config.get_controller().is_gamepad())
return option.getDisplayPrefix() + Formatting.GOLD + controller_name;
this.controllerOption = new SpruceCyclingOption("lambdacontrols.menu.controller", amount -> {
int id = this.mod.config.getController().getId();
id += amount;
if (id > GLFW.GLFW_JOYSTICK_LAST)
id = GLFW.GLFW_JOYSTICK_1;
this.mod.config.setController(Controller.byId(id));
}, option -> {
String controllerName = this.mod.config.getController().getName();
if (!this.mod.config.getController().isConnected())
return option.getDisplayPrefix() + Formatting.RED + controllerName;
else if (!this.mod.config.getController().isGamepad())
return option.getDisplayPrefix() + Formatting.GOLD + controllerName;
else
return option.getDisplayPrefix() + controller_name;
});
this.second_controller_option = new SpruceCyclingOption("lambdacontrols.menu.controller2",
(game_options, amount) -> {
int current_id = this.mod.config.get_second_controller().map(Controller::get_id).orElse(-1);
current_id += amount;
if (current_id > GLFW.GLFW_JOYSTICK_LAST)
current_id = -1;
this.mod.config.set_second_controller(current_id == -1 ? null : Controller.by_id(current_id));
}, (game_options, option) -> this.mod.config.get_second_controller().map(controller -> {
String controller_name = controller.get_name();
if (!controller.is_connected())
return option.getDisplayPrefix() + Formatting.RED + controller_name;
else if (!controller.is_gamepad())
return option.getDisplayPrefix() + Formatting.GOLD + controller_name;
return option.getDisplayPrefix() + controllerName;
}, null);
this.secondControllerOption = new SpruceCyclingOption("lambdacontrols.menu.controller2",
amount -> {
int id = this.mod.config.getSecondController().map(Controller::getId).orElse(-1);
id += amount;
if (id > GLFW.GLFW_JOYSTICK_LAST)
id = -1;
this.mod.config.setSecondController(id == -1 ? null : Controller.byId(id));
}, option -> this.mod.config.getSecondController().map(controller -> {
String controllerName = controller.getName();
if (!controller.isConnected())
return option.getDisplayPrefix() + Formatting.RED + controllerName;
else if (!controller.isGamepad())
return option.getDisplayPrefix() + Formatting.GOLD + controllerName;
else
return option.getDisplayPrefix() + controller_name;
return option.getDisplayPrefix() + controllerName;
}).orElse(option.getDisplayPrefix() + Formatting.RED + I18n.translate("options.off")),
new TranslatableText("lambdacontrols.tooltip.controller2"));
this.controller_type_option = new SpruceCyclingOption("lambdacontrols.menu.controller_type",
(game_options, amount) -> this.mod.config.set_controller_type(this.mod.config.get_controller_type().next()),
(game_options, option) -> option.getDisplayPrefix() + this.mod.config.get_controller_type().get_translated_name(),
this.controllerTypeOption = new SpruceCyclingOption("lambdacontrols.menu.controller_type",
amount -> this.mod.config.setControllerType(this.mod.config.getControllerType().next()),
option -> option.getDisplayPrefix() + this.mod.config.getControllerType().getTranslatedName(),
new TranslatableText("lambdacontrols.tooltip.controller_type"));
this.dead_zone_option = new SpruceDoubleOption("lambdacontrols.menu.dead_zone", 0.05, 1.0, 0.05F, game_options -> this.mod.config.get_dead_zone(),
(game_options, new_value) -> {
this.deadZoneOption = new SpruceDoubleOption("lambdacontrols.menu.dead_zone", 0.05, 1.0, 0.05F, this.mod.config::getDeadZone,
newValue -> {
synchronized (this.mod.config) {
this.mod.config.set_dead_zone(new_value);
this.mod.config.setDeadZone(newValue);
}
}, (game_options, option) -> {
String value = String.valueOf(option.get(options));
}, option -> {
String value = String.valueOf(option.get());
return option.getDisplayPrefix() + value.substring(0, Math.min(value.length(), 5));
}, new TranslatableText("lambdacontrols.tooltip.dead_zone"));
this.inverts_right_x_axis = new SpruceBooleanOption("lambdacontrols.menu.invert_right_x_axis", game_options -> this.mod.config.does_invert_right_x_axis(),
(game_options, new_value) -> {
this.invertsRightXAxis = new SpruceBooleanOption("lambdacontrols.menu.invert_right_x_axis", this.mod.config::doesInvertRightXAxis,
newValue -> {
synchronized (this.mod.config) {
this.mod.config.set_invert_right_x_axis(new_value);
this.mod.config.setInvertRightXAxis(newValue);
}
}, null, true);
this.inverts_right_y_axis = new SpruceBooleanOption("lambdacontrols.menu.invert_right_y_axis", game_options -> this.mod.config.does_invert_right_y_axis(),
(game_options, new_value) -> {
this.invertsRightYAxis = new SpruceBooleanOption("lambdacontrols.menu.invert_right_y_axis", this.mod.config::doesInvertRightYAxis,
newValue -> {
synchronized (this.mod.config) {
this.mod.config.set_invert_right_y_axis(new_value);
this.mod.config.setInvertRightYAxis(newValue);
}
}, null, true);
this.unfocused_input_option = new SpruceBooleanOption("lambdacontrols.menu.unfocused_input", (game_options) -> this.mod.config.has_unfocused_input(),
(game_options, new_value) -> this.mod.config.set_unfocused_input(new_value), new TranslatableText("lambdacontrols.tooltip.unfocused_input"), true);
this.unfocusedInputOption = new SpruceBooleanOption("lambdacontrols.menu.unfocused_input", this.mod.config::hasUnfocusedInput,
this.mod.config::setUnfocusedInput, new TranslatableText("lambdacontrols.tooltip.unfocused_input"), true);
// HUD options
this.hud_enable_option = new SpruceBooleanOption("lambdacontrols.menu.hud_enable", (game_options) -> this.mod.config.is_hud_enabled(),
(game_options, new_value) -> this.mod.config.set_hud_enabled(new_value), new TranslatableText("lambdacontrols.tooltip.hud_enable"), true);
this.hud_side_option = new SpruceCyclingOption("lambdacontrols.menu.hud_side",
(game_options, amount) -> this.mod.config.set_hud_side(this.mod.config.get_hud_side().next()),
(game_options, option) -> option.getDisplayPrefix() + this.mod.config.get_hud_side().get_translated_name(),
this.hudEnableOption = new SpruceBooleanOption("lambdacontrols.menu.hud_enable", this.mod.config::isHudEnabled,
this.mod::setHudEnabled, new TranslatableText("lambdacontrols.tooltip.hud_enable"), true);
this.hudSideOption = new SpruceCyclingOption("lambdacontrols.menu.hud_side",
amount -> this.mod.config.setHudSide(this.mod.config.getHudSide().next()),
option -> option.getDisplayPrefix() + this.mod.config.getHudSide().getTranslatedName(),
new TranslatableText("lambdacontrols.tooltip.hud_side"));
}
@@ -179,7 +183,7 @@ public class LambdaControlsSettingsScreen extends Screen
super.onClose();
}
private int get_text_height()
private int getTextHeight()
{
return (5 + this.font.fontHeight) * 3 + 5;
}
@@ -188,69 +192,74 @@ public class LambdaControlsSettingsScreen extends Screen
protected void init()
{
super.init();
int button_height = 20;
SpruceButtonWidget controls_mode_btn = new SpruceButtonWidget(this.width / 2 - 155, 18, this.hide_controls ? 310 : 150, button_height,
I18n.translate("lambdacontrols.menu.controls_mode") + ": " + I18n.translate(this.mod.config.get_controls_mode().get_translation_key()),
int buttonHeight = 20;
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()),
btn -> {
ControlsMode next = this.mod.config.get_controls_mode().next();
btn.setMessage(I18n.translate("lambdacontrols.menu.controls_mode") + ": " + I18n.translate(next.get_translation_key()));
this.mod.config.set_controls_mode(next);
ControlsMode next = this.mod.config.getControlsMode().next();
btn.setMessage(I18n.translate("lambdacontrols.menu.controls_mode") + ": " + I18n.translate(next.getTranslationKey()));
this.mod.config.setControlsMode(next);
this.mod.config.save();
if (this.minecraft.player != null) {
ClientSidePacketRegistry.INSTANCE.sendToServer(LambdaControls.CONTROLS_MODE_CHANNEL, this.mod.makeControlsModeBuffer(next));
}
});
controls_mode_btn.set_tooltip(new TranslatableText("lambdacontrols.tooltip.controls_mode"));
this.addButton(controls_mode_btn);
if (!this.hide_controls)
this.addButton(new ButtonWidget(this.width / 2 - 155 + 160, 18, 150, button_height, I18n.translate("options.controls"),
controlsModeBtn.setTooltip(new TranslatableText("lambdacontrols.tooltip.controls_mode"));
this.addButton(controlsModeBtn);
if (!this.hideControls)
this.addButton(new ButtonWidget(this.width / 2 - 155 + 160, 18, 150, buttonHeight, I18n.translate("options.controls"),
btn -> {
if (this.mod.config.get_controls_mode() == ControlsMode.CONTROLLER)
this.minecraft.openScreen(new LambdaControlsControlsScreen(this, true));
if (this.mod.config.getControlsMode() == ControlsMode.CONTROLLER)
this.minecraft.openScreen(new ControllerControlsScreen(this, true));
else
this.minecraft.openScreen(new ControlsOptionsScreen(this, this.minecraft.options));
}));
this.list = new ButtonListWidget(this.minecraft, this.width, this.height, 43, this.height - 29 - this.get_text_height(), 25);
this.list = new ButtonListWidget(this.minecraft, this.width, this.height, 43, this.height - 29 - this.getTextHeight(), 25);
// General options
this.list.addSingleOptionEntry(new SpruceSeparatorOption("lambdacontrols.menu.title.general", true, null));
this.list.addOptionEntry(this.rotation_speed_option, this.mouse_speed_option);
this.list.addSingleOptionEntry(this.auto_switch_mode_option);
this.list.addOptionEntry(this.rotationSpeedOption, this.mouseSpeedOption);
this.list.addSingleOptionEntry(this.autoSwitchModeOption);
// Gameplay options
this.list.addSingleOptionEntry(new SpruceSeparatorOption("lambdacontrols.menu.title.gameplay", true, null));
this.list.addSingleOptionEntry(this.front_block_placing_option);
this.list.addSingleOptionEntry(this.fly_drifting_option);
this.list.addSingleOptionEntry(this.frontBlockPlacingOption);
this.list.addSingleOptionEntry(this.flyDriftingOption);
this.list.addSingleOptionEntry(this.flyVerticalDriftingOption);
// Controller options
this.list.addSingleOptionEntry(new SpruceSeparatorOption("lambdacontrols.menu.title.controller", true, null));
this.list.addSingleOptionEntry(this.controller_option);
this.list.addSingleOptionEntry(this.second_controller_option);
this.list.addOptionEntry(this.controller_type_option, this.dead_zone_option);
this.list.addOptionEntry(this.inverts_right_x_axis, this.inverts_right_y_axis);
this.list.addSingleOptionEntry(this.unfocused_input_option);
this.list.addSingleOptionEntry(this.controllerOption);
this.list.addSingleOptionEntry(this.secondControllerOption);
this.list.addOptionEntry(this.controllerTypeOption, this.deadZoneOption);
this.list.addOptionEntry(this.invertsRightXAxis, this.invertsRightYAxis);
this.list.addSingleOptionEntry(this.unfocusedInputOption);
this.list.addSingleOptionEntry(new ReloadControllerMappingsOption());
// HUD options
this.list.addSingleOptionEntry(new SpruceSeparatorOption("lambdacontrols.menu.title.hud", true, null));
this.list.addOptionEntry(this.hud_enable_option, this.hud_side_option);
this.list.addOptionEntry(this.hudEnableOption, this.hudSideOption);
this.children.add(this.list);
this.gamepad_tool_url_label = new SpruceLabelWidget(this.width / 2, this.height - 29 - (5 + this.font.fontHeight) * 2, this.controller_mappings_url_text, this.width,
this.gamepadToolUrlLabel = new SpruceLabelWidget(this.width / 2, this.height - 29 - (5 + this.font.fontHeight) * 2, this.controllerMappingsUrlText, this.width,
label -> Util.getOperatingSystem().open(GAMEPAD_TOOL_URL), true);
this.gamepad_tool_url_label.set_tooltip(new TranslatableText("chat.link.open"));
this.children.add(this.gamepad_tool_url_label);
this.gamepadToolUrlLabel.setTooltip(new TranslatableText("chat.link.open"));
this.children.add(this.gamepadToolUrlLabel);
this.addButton(this.reset_option.createButton(this.minecraft.options, this.width / 2 - 155, this.height - 29, 150));
this.addButton(new ButtonWidget(this.width / 2 - 155 + 160, this.height - 29, 150, button_height, I18n.translate("gui.done"),
this.addButton(this.resetOption.createButton(this.minecraft.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"),
(buttonWidget) -> this.minecraft.openScreen(this.parent)));
}
@Override
public void render(int mouse_x, int mouse_y, float delta)
public void render(int mouseX, int mouseY, float delta)
{
this.renderBackground();
this.list.render(mouse_x, mouse_y, delta);
super.render(mouse_x, mouse_y, delta);
this.list.render(mouseX, mouseY, delta);
super.render(mouseX, mouseY, delta);
this.drawCenteredString(this.font, 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.gamepad_tool_url_label.render(mouse_x, mouse_y, delta);
this.gamepadToolUrlLabel.render(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);
Tooltip.render_all();
Tooltip.renderAll();
}
}

View File

@@ -36,19 +36,19 @@ public class ReloadControllerMappingsOption extends Option implements Nameable
@Override
public AbstractButtonWidget createButton(GameOptions options, int x, int y, int width)
{
SpruceButtonWidget button = new SpruceButtonWidget(x, y, width, 20, this.get_name(), btn -> {
SpruceButtonWidget button = new SpruceButtonWidget(x, y, width, 20, this.getName(), btn -> {
MinecraftClient client = MinecraftClient.getInstance();
Controller.update_mappings();
Controller.updateMappings();
if (client.currentScreen != null)
client.currentScreen.init(client, client.getWindow().getScaledWidth(), client.getWindow().getScaledHeight());
client.getToastManager().add(new SystemToast(SystemToast.Type.TUTORIAL_HINT, new TranslatableText("lambdacontrols.controller.mappings.updated"), null));
});
button.set_tooltip(new TranslatableText("lambdacontrols.tooltip.reload_controller_mappings"));
button.setTooltip(new TranslatableText("lambdacontrols.tooltip.reload_controller_mappings"));
return button;
}
@Override
public @NotNull String get_name()
public @NotNull String getName()
{
return I18n.translate(KEY);
}

View File

@@ -36,18 +36,18 @@ import static org.lwjgl.glfw.GLFW.GLFW_GAMEPAD_AXIS_RIGHT_Y;
*/
public class TouchscreenOverlay extends Screen
{
public static final Identifier WIDGETS_LOCATION = new Identifier("lambdacontrols", "textures/gui/widgets.png");
public static final Identifier WIDGETS_LOCATION = new Identifier("lambdacontrols", "textures/gui/widgets.png");
private LambdaControlsClient mod;
private SpruceTexturedButtonWidget jump_button;
private SpruceTexturedButtonWidget fly_button;
private SpruceTexturedButtonWidget fly_up_button;
private SpruceTexturedButtonWidget fly_down_button;
private int fly_button_enable_ticks = 0;
private int forward_button_tick = 0;
private SpruceTexturedButtonWidget forward_left_button;
private SpruceTexturedButtonWidget forward_right_button;
private SpruceTexturedButtonWidget start_sneak_button;
private SpruceTexturedButtonWidget end_sneak_button;
private SpruceTexturedButtonWidget jumpButton;
private SpruceTexturedButtonWidget flyButton;
private SpruceTexturedButtonWidget flyUpButton;
private SpruceTexturedButtonWidget flyDownButton;
private int flyButtonEnableTicks = 0;
private int forwardButtonTick = 0;
private SpruceTexturedButtonWidget forwardLeftButton;
private SpruceTexturedButtonWidget forwardRightButton;
private SpruceTexturedButtonWidget startSneakButton;
private SpruceTexturedButtonWidget endSneakButton;
public TouchscreenOverlay(@NotNull LambdaControlsClient mod)
{
@@ -68,7 +68,7 @@ public class TouchscreenOverlay extends Screen
return false;
}
private void pause_game(boolean bl)
private void pauseGame(boolean bl)
{
if (this.minecraft == null)
return;
@@ -86,37 +86,37 @@ public class TouchscreenOverlay extends Screen
*
* @param state The button state.
*/
private void update_forward_buttons_state(boolean state)
private void updateForwardButtonsState(boolean state)
{
if (state)
this.forward_button_tick = -1;
this.forwardButtonTick = -1;
else
this.forward_button_tick = 20;
this.forwardButtonTick = 20;
}
/**
* Updates the jump buttons.
*/
private void update_jump_buttons()
private void updateJumpButtons()
{
if (this.minecraft == null)
return;
if (this.minecraft.player.abilities.allowFlying && this.minecraft.player.abilities.flying) {
boolean old_state_fly = this.fly_button.visible;
this.jump_button.visible = false;
this.fly_button.visible = true;
this.fly_up_button.visible = true;
this.fly_down_button.visible = true;
if (old_state_fly != this.fly_button.visible) {
this.fly_button_enable_ticks = 5;
this.handle_jump(null, false);
} else if (this.fly_button_enable_ticks > 0)
this.fly_button_enable_ticks--;
boolean oldStateFly = this.flyButton.visible;
this.jumpButton.visible = false;
this.flyButton.visible = true;
this.flyUpButton.visible = true;
this.flyDownButton.visible = true;
if (oldStateFly != this.flyButton.visible) {
this.flyButtonEnableTicks = 5;
this.handleJump(null, false);
} else if (this.flyButtonEnableTicks > 0)
this.flyButtonEnableTicks--;
} else {
this.jump_button.visible = true;
this.fly_button.visible = false;
this.fly_up_button.visible = false;
this.fly_down_button.visible = false;
this.jumpButton.visible = true;
this.flyButton.visible = false;
this.flyUpButton.visible = false;
this.flyDownButton.visible = false;
}
}
@@ -126,44 +126,44 @@ public class TouchscreenOverlay extends Screen
* @param btn The pressed button.
* @param state The state of the jump button.
*/
private void handle_jump(ButtonWidget btn, boolean state)
private void handleJump(ButtonWidget btn, boolean state)
{
((KeyBindingAccessor) this.minecraft.options.keyJump).handle_press_state(state);
((KeyBindingAccessor) this.minecraft.options.keyJump).lambdacontrols_handlePressState(state);
}
@Override
public void tick()
{
if (this.forward_button_tick > 0) {
this.forward_button_tick--;
} else if (this.forward_button_tick == 0) {
if (this.forward_left_button.visible)
this.forward_left_button.visible = false;
if (this.forward_right_button.visible)
this.forward_right_button.visible = false;
if (this.forwardButtonTick > 0) {
this.forwardButtonTick--;
} else if (this.forwardButtonTick == 0) {
if (this.forwardLeftButton.visible)
this.forwardLeftButton.visible = false;
if (this.forwardRightButton.visible)
this.forwardRightButton.visible = false;
}
this.update_jump_buttons();
this.updateJumpButtons();
}
@Override
protected void init()
{
super.init();
int scaled_width = this.minecraft.getWindow().getScaledWidth();
int scaled_height = this.minecraft.getWindow().getScaledHeight();
this.addButton(new TexturedButtonWidget(scaled_width / 2 - 20, 0, 20, 20, 0, 106, 20, ButtonWidget.WIDGETS_LOCATION, 256, 256,
int scaledWidth = this.minecraft.getWindow().getScaledWidth();
int scaledHeight = this.minecraft.getWindow().getScaledHeight();
this.addButton(new TexturedButtonWidget(scaledWidth / 2 - 20, 0, 20, 20, 0, 106, 20, ButtonWidget.WIDGETS_LOCATION, 256, 256,
btn -> this.minecraft.openScreen(new ChatScreen("")), ""));
this.addButton(new TexturedButtonWidget(scaled_width / 2, 0, 20, 20, 0, 0, 20, WIDGETS_LOCATION, 256, 256,
btn -> this.pause_game(false)));
this.addButton(new TexturedButtonWidget(scaledWidth / 2, 0, 20, 20, 0, 0, 20, WIDGETS_LOCATION, 256, 256,
btn -> this.pauseGame(false)));
// Inventory buttons.
int inventory_button_x = scaled_width / 2;
int inventory_button_y = scaled_height - 16 - 5;
int inventoryButtonX = scaledWidth / 2;
int inventoryButtonY = scaledHeight - 16 - 5;
if (this.minecraft.options.mainArm == Arm.LEFT) {
inventory_button_x = inventory_button_x - 91 - 24;
inventoryButtonX = inventoryButtonX - 91 - 24;
} else {
inventory_button_x = inventory_button_x + 91 + 4;
inventoryButtonX = inventoryButtonX + 91 + 4;
}
this.addButton(new TexturedButtonWidget(inventory_button_x, inventory_button_y, 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 -> {
if (this.minecraft.interactionManager.hasRidingInventory()) {
this.minecraft.player.openRidingInventory();
@@ -172,19 +172,19 @@ public class TouchscreenOverlay extends Screen
this.minecraft.openScreen(new InventoryScreen(this.minecraft.player));
}
}));
int jump_button_x, swap_hands_x, sneak_button_x;
int sneak_button_y = scaled_height - 10 - 40 - 5;
if (this.mod.config.get_hud_side() == HudSide.LEFT) {
jump_button_x = scaled_width - 20 - 20;
swap_hands_x = jump_button_x - 5 - 40;
sneak_button_x = 10 + 20 + 5;
int jumpButtonX, swapHandsX, sneakButtonX;
int sneakButtonY = scaledHeight - 10 - 40 - 5;
if (this.mod.config.getHudSide() == HudSide.LEFT) {
jumpButtonX = scaledWidth - 20 - 20;
swapHandsX = jumpButtonX - 5 - 40;
sneakButtonX = 10 + 20 + 5;
} else {
jump_button_x = 20;
swap_hands_x = jump_button_x + 5 + 40;
sneak_button_x = scaled_width - 10 - 40 - 5;
jumpButtonX = 20;
swapHandsX = jumpButtonX + 5 + 40;
sneakButtonX = scaledWidth - 10 - 40 - 5;
}
// Swap items hand.
this.addButton(new SpruceTexturedButtonWidget(swap_hands_x, sneak_button_y, 20, 20, 0, 160, 20, WIDGETS_LOCATION,
this.addButton(new SpruceTexturedButtonWidget(swapHandsX, sneakButtonY, 20, 20, 0, 160, 20, WIDGETS_LOCATION,
(btn, state) -> {
if (state) {
if (!this.minecraft.player.isSpectator()) {
@@ -193,65 +193,65 @@ public class TouchscreenOverlay extends Screen
}
}));
// Drop
this.addButton(new SpruceTexturedButtonWidget(swap_hands_x, sneak_button_y + 5 + 20, 20, 20, 20, 160, 20, WIDGETS_LOCATION,
(btn, state) -> ((KeyBindingAccessor) this.minecraft.options.keyDrop).handle_press_state(state)));
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)));
// Jump keys
this.addButton(this.jump_button = new SpruceTexturedButtonWidget(jump_button_x, sneak_button_y, 20, 20, 0, 40, 20, WIDGETS_LOCATION,
this::handle_jump));
this.addButton(this.fly_button = new SpruceTexturedButtonWidget(jump_button_x, sneak_button_y, 20, 20, 20, 40, 20, WIDGETS_LOCATION,
this.addButton(this.jumpButton = new SpruceTexturedButtonWidget(jumpButtonX, sneakButtonY, 20, 20, 0, 40, 20, WIDGETS_LOCATION,
this::handleJump));
this.addButton(this.flyButton = new SpruceTexturedButtonWidget(jumpButtonX, sneakButtonY, 20, 20, 20, 40, 20, WIDGETS_LOCATION,
(btn, state) -> {
if (this.fly_button_enable_ticks == 0) this.minecraft.player.abilities.flying = false;
if (this.flyButtonEnableTicks == 0) this.minecraft.player.abilities.flying = false;
}));
this.addButton(this.fly_up_button = new SpruceTexturedButtonWidget(jump_button_x, sneak_button_y - 5 - 20, 20, 20, 40, 40, 20, WIDGETS_LOCATION,
this::handle_jump));
this.addButton(this.fly_down_button = new SpruceTexturedButtonWidget(jump_button_x, sneak_button_y + 20 + 5, 20, 20, 60, 40, 20, WIDGETS_LOCATION,
(btn, state) -> ((KeyBindingAccessor) this.minecraft.options.keySneak).handle_press_state(state)));
this.update_jump_buttons();
this.addButton(this.flyUpButton = new SpruceTexturedButtonWidget(jumpButtonX, sneakButtonY - 5 - 20, 20, 20, 40, 40, 20, WIDGETS_LOCATION,
this::handleJump));
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)));
this.updateJumpButtons();
// Movements keys
this.addButton((this.start_sneak_button = new SpruceTexturedButtonWidget(sneak_button_x, sneak_button_y, 20, 20, 0, 120, 20, WIDGETS_LOCATION,
this.addButton((this.startSneakButton = new SpruceTexturedButtonWidget(sneakButtonX, sneakButtonY, 20, 20, 0, 120, 20, WIDGETS_LOCATION,
(btn, state) -> {
if (state) {
((KeyBindingAccessor) this.minecraft.options.keySneak).handle_press_state(true);
this.start_sneak_button.visible = false;
this.end_sneak_button.visible = true;
((KeyBindingAccessor) this.minecraft.options.keySneak).lambdacontrols_handlePressState(true);
this.startSneakButton.visible = false;
this.endSneakButton.visible = true;
}
})));
this.addButton((this.end_sneak_button = new SpruceTexturedButtonWidget(sneak_button_x, sneak_button_y, 20, 20, 20, 120, 20, WIDGETS_LOCATION,
this.addButton((this.endSneakButton = new SpruceTexturedButtonWidget(sneakButtonX, sneakButtonY, 20, 20, 20, 120, 20, WIDGETS_LOCATION,
(btn, state) -> {
if (state) {
((KeyBindingAccessor) this.minecraft.options.keySneak).handle_press_state(false);
this.end_sneak_button.visible = false;
this.start_sneak_button.visible = true;
((KeyBindingAccessor) this.minecraft.options.keySneak).lambdacontrols_handlePressState(false);
this.endSneakButton.visible = false;
this.startSneakButton.visible = true;
}
})));
this.end_sneak_button.visible = false;
this.addButton(this.forward_left_button = new SpruceTexturedButtonWidget(sneak_button_x - 20 - 5, sneak_button_y - 5 - 20, 20, 20, 80, 80, 20, WIDGETS_LOCATION,
this.endSneakButton.visible = false;
this.addButton(this.forwardLeftButton = new SpruceTexturedButtonWidget(sneakButtonX - 20 - 5, sneakButtonY - 5 - 20, 20, 20, 80, 80, 20, WIDGETS_LOCATION,
(btn, state) -> {
((KeyBindingAccessor) this.minecraft.options.keyForward).handle_press_state(state);
((KeyBindingAccessor) this.minecraft.options.keyLeft).handle_press_state(state);
this.update_forward_buttons_state(state);
((KeyBindingAccessor) this.minecraft.options.keyForward).lambdacontrols_handlePressState(state);
((KeyBindingAccessor) this.minecraft.options.keyLeft).lambdacontrols_handlePressState(state);
this.updateForwardButtonsState(state);
}));
this.forward_left_button.visible = false;
this.addButton(new SpruceTexturedButtonWidget(sneak_button_x, sneak_button_y - 5 - 20, 20, 20, 0, 80, 20, WIDGETS_LOCATION,
this.forwardLeftButton.visible = false;
this.addButton(new SpruceTexturedButtonWidget(sneakButtonX, sneakButtonY - 5 - 20, 20, 20, 0, 80, 20, WIDGETS_LOCATION,
(btn, state) -> {
((KeyBindingAccessor) this.minecraft.options.keyForward).handle_press_state(state);
this.update_forward_buttons_state(state);
this.forward_left_button.visible = true;
this.forward_right_button.visible = true;
((KeyBindingAccessor) this.minecraft.options.keyForward).lambdacontrols_handlePressState(state);
this.updateForwardButtonsState(state);
this.forwardLeftButton.visible = true;
this.forwardRightButton.visible = true;
}));
this.addButton(this.forward_right_button = new SpruceTexturedButtonWidget(sneak_button_x + 20 + 5, sneak_button_y - 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) -> {
((KeyBindingAccessor) this.minecraft.options.keyForward).handle_press_state(state);
((KeyBindingAccessor) this.minecraft.options.keyRight).handle_press_state(state);
this.update_forward_buttons_state(state);
((KeyBindingAccessor) this.minecraft.options.keyForward).lambdacontrols_handlePressState(state);
((KeyBindingAccessor) this.minecraft.options.keyRight).lambdacontrols_handlePressState(state);
this.updateForwardButtonsState(state);
}));
this.forward_right_button.visible = true;
this.addButton(new SpruceTexturedButtonWidget(sneak_button_x + 20 + 5, sneak_button_y, 20, 20, 20, 80, 20, WIDGETS_LOCATION,
(btn, state) -> ((KeyBindingAccessor) this.minecraft.options.keyRight).handle_press_state(state)));
this.addButton(new SpruceTexturedButtonWidget(sneak_button_x, sneak_button_y + 20 + 5, 20, 20, 40, 80, 20, WIDGETS_LOCATION,
(btn, state) -> ((KeyBindingAccessor) this.minecraft.options.keyBack).handle_press_state(state)));
this.addButton(new SpruceTexturedButtonWidget(sneak_button_x - 20 - 5, sneak_button_y, 20, 20, 60, 80, 20, WIDGETS_LOCATION,
(btn, state) -> ((KeyBindingAccessor) this.minecraft.options.keyLeft).handle_press_state(state)));
this.forwardRightButton.visible = true;
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)));
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)));
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)));
}
@Override
@@ -261,37 +261,37 @@ public class TouchscreenOverlay extends Screen
}
@Override
public boolean mouseClicked(double mouse_x, double mouse_y, int button)
public boolean mouseClicked(double mouseX, double mouseY, int button)
{
if (mouse_y >= (double) (this.height - 22) && this.minecraft != null && this.minecraft.player != null) {
int center_x = this.width / 2;
if (mouse_x >= (double) (center_x - 90) && mouse_x <= (double) (center_x + 90)) {
if (mouseY >= (double) (this.height - 22) && this.minecraft != null && this.minecraft.player != null) {
int centerX = this.width / 2;
if (mouseX >= (double) (centerX - 90) && mouseX <= (double) (centerX + 90)) {
for (int slot = 0; slot < 9; ++slot) {
int slot_x = center_x - 90 + slot * 20 + 2;
if (mouse_x >= (double) slot_x && mouse_x <= (double) (slot_x + 20)) {
int slotX = centerX - 90 + slot * 20 + 2;
if (mouseX >= (double) slotX && mouseX <= (double) (slotX + 20)) {
this.minecraft.player.inventory.selectedSlot = slot;
return true;
}
}
}
}
return super.mouseClicked(mouse_x, mouse_y, button);
return super.mouseClicked(mouseX, mouseY, button);
}
@Override
public boolean mouseDragged(double mouse_x, double mouse_y, int button, double delta_x, double delta_y)
public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY)
{
if (button == GLFW.GLFW_MOUSE_BUTTON_1 && this.minecraft != null) {
if (delta_y > 0.01)
this.mod.input.handle_look(this.minecraft, GLFW_GAMEPAD_AXIS_RIGHT_Y, (float) Math.abs(delta_y / 5.0), 2);
else if (delta_y < 0.01)
this.mod.input.handle_look(this.minecraft, GLFW_GAMEPAD_AXIS_RIGHT_Y, (float) Math.abs(delta_y / 5.0), 1);
if (deltaY > 0.01)
this.mod.input.handleLook(this.minecraft, GLFW_GAMEPAD_AXIS_RIGHT_Y, (float) Math.abs(deltaY / 5.0), 2);
else if (deltaY < 0.01)
this.mod.input.handleLook(this.minecraft, GLFW_GAMEPAD_AXIS_RIGHT_Y, (float) Math.abs(deltaY / 5.0), 1);
if (delta_x > 0.01)
this.mod.input.handle_look(this.minecraft, GLFW_GAMEPAD_AXIS_RIGHT_X, (float) Math.abs(delta_x / 5.0), 2);
else if (delta_x < 0.01)
this.mod.input.handle_look(this.minecraft, GLFW_GAMEPAD_AXIS_RIGHT_X, (float) Math.abs(delta_x / 5.0), 1);
if (deltaX > 0.01)
this.mod.input.handleLook(this.minecraft, GLFW_GAMEPAD_AXIS_RIGHT_X, (float) Math.abs(deltaX / 5.0), 2);
else if (deltaX < 0.01)
this.mod.input.handleLook(this.minecraft, GLFW_GAMEPAD_AXIS_RIGHT_X, (float) Math.abs(deltaX / 5.0), 1);
}
return super.mouseDragged(mouse_x, mouse_y, button, delta_x, delta_y);
return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY);
}
}

View File

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

View File

@@ -0,0 +1,35 @@
/*
* 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.advancement.Advancement;
import net.minecraft.client.gui.screen.advancement.AdvancementTab;
import net.minecraft.client.gui.screen.advancement.AdvancementsScreen;
import net.minecraft.client.network.ClientAdvancementManager;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import java.util.Map;
/**
* Represents an accessor of {@link AdvancementsScreen}.
*/
@Mixin(AdvancementsScreen.class)
public interface AdvancementsScreenAccessor
{
@Accessor("advancementHandler")
ClientAdvancementManager lambdacontrols_getAdvancementManager();
@Accessor("tabs")
Map<Advancement, AdvancementTab> lambdacontrols_getTabs();
@Accessor("selectedTab")
AdvancementTab lambdacontrols_getSelectedTab();
}

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

View File

@@ -11,11 +11,14 @@ package me.lambdaurora.lambdacontrols.client.mixin;
import com.mojang.authlib.GameProfile;
import me.lambdaurora.lambdacontrols.client.LambdaControlsClient;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.input.Input;
import net.minecraft.client.network.AbstractClientPlayerEntity;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.entity.MovementType;
import net.minecraft.util.math.Vec3d;
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;
@@ -28,11 +31,21 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(ClientPlayerEntity.class)
public abstract class ClientPlayerEntityMixin extends AbstractClientPlayerEntity
{
private boolean lambdacontrols_drifting_prevented = false;
private boolean lambdacontrols_driftingPrevented = false;
@Shadow
protected abstract boolean hasMovementInput();
@Shadow
@Final
protected MinecraftClient client;
@Shadow
public Input input;
@Shadow
protected abstract boolean isCamera();
public ClientPlayerEntityMixin(ClientWorld world, GameProfile profile)
{
super(world, profile);
@@ -43,14 +56,36 @@ public abstract class ClientPlayerEntityMixin extends AbstractClientPlayerEntity
{
LambdaControlsClient mod = LambdaControlsClient.get();
if (type == MovementType.SELF) {
if (this.abilities.flying && !mod.config.has_fly_drifting()) {
if (this.abilities.flying && (!mod.config.hasFlyDrifting() || !mod.config.hasFlyVerticalDrifting())) {
if (!this.hasMovementInput()) {
if (!this.lambdacontrols_drifting_prevented) {
this.setVelocity(this.getVelocity().multiply(0, 1.0, 0));
if (!this.lambdacontrols_driftingPrevented) {
if (!mod.config.hasFlyDrifting())
this.setVelocity(this.getVelocity().multiply(0, 1.0, 0));
}
this.lambdacontrols_drifting_prevented = true;
this.lambdacontrols_driftingPrevented = true;
} else
this.lambdacontrols_drifting_prevented = false;
this.lambdacontrols_driftingPrevented = false;
}
}
}
@Inject(method = "tickMovement", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;isCamera()Z"))
public void lambdacontrols_tickMovement(CallbackInfo ci)
{
if (this.abilities.flying && this.isCamera()) {
if (LambdaControlsClient.get().config.hasFlyVerticalDrifting())
return;
int moving = 0;
if (this.input.sneaking) {
--moving;
}
if (this.input.jumping) {
++moving;
}
if (moving == 0) {
this.setVelocity(this.getVelocity().multiply(1.0, 0.0, 1.0));
}
}
}

View File

@@ -11,9 +11,9 @@ package me.lambdaurora.lambdacontrols.client.mixin;
import me.lambdaurora.lambdacontrols.ControlsMode;
import me.lambdaurora.lambdacontrols.client.LambdaControlsClient;
import me.lambdaurora.lambdacontrols.client.util.AbstractContainerScreenAccessor;
import me.lambdaurora.lambdacontrols.client.util.ContainerScreenAccessor;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.ingame.AbstractContainerScreen;
import net.minecraft.client.gui.screen.ingame.ContainerScreen;
import net.minecraft.container.Slot;
import org.lwjgl.glfw.GLFW;
import org.spongepowered.asm.mixin.Mixin;
@@ -23,40 +23,40 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
/**
* Represents the mixin for the class AbstractContainerScreen.
* Represents the mixin for the class ContainerScreen.
*/
@Mixin(AbstractContainerScreen.class)
public abstract class AbstractContainerScreenMixin implements AbstractContainerScreenAccessor
@Mixin(ContainerScreen.class)
public abstract class ContainerScreenMixin implements ContainerScreenAccessor
{
protected int x;
protected int y;
@Override
public int lambdacontrols_get_x()
public int lambdacontrols_getX()
{
return this.x;
}
@Override
public int lambdacontrols_get_y()
public int lambdacontrols_getY()
{
return this.y;
}
@Invoker("getSlotAt")
public abstract Slot lambdacontrols_get_slot_at(double pos_x, double pos_y);
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.get_controls_mode() == ControlsMode.CONTROLLER) {
if (LambdaControlsClient.get().config.getControlsMode() == ControlsMode.CONTROLLER) {
MinecraftClient client = MinecraftClient.getInstance();
int x = 10, y = client.getWindow().getScaledHeight() - 10 - 15;
x += LambdaControlsClient.draw_button_tip(x, y, new int[]{GLFW.GLFW_GAMEPAD_BUTTON_A}, "lambdacontrols.action.pickup_all", true, client) + 10;
x += LambdaControlsClient.draw_button_tip(x, y, new int[]{GLFW.GLFW_GAMEPAD_BUTTON_B}, "lambdacontrols.action.exit", true, client) + 10;
x += LambdaControlsClient.draw_button_tip(x, y, new int[]{GLFW.GLFW_GAMEPAD_BUTTON_X}, "lambdacontrols.action.pickup", true, client) + 10;
LambdaControlsClient.draw_button_tip(x, y, new int[]{GLFW.GLFW_GAMEPAD_BUTTON_Y}, "lambdacontrols.action.quick_move", true, client);
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

@@ -9,7 +9,7 @@
package me.lambdaurora.lambdacontrols.client.mixin;
import me.lambdaurora.lambdacontrols.client.gui.LambdaControlsControlsScreen;
import me.lambdaurora.lambdacontrols.client.gui.ControllerControlsScreen;
import me.lambdaurora.lambdacontrols.client.gui.LambdaControlsSettingsScreen;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.screen.options.ControlsOptionsScreen;
@@ -29,18 +29,18 @@ import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(ControlsOptionsScreen.class)
public class ControlsOptionsScreenMixin extends GameOptionsScreen
{
public ControlsOptionsScreenMixin(Screen parent, GameOptions game_options, Text text)
public ControlsOptionsScreenMixin(Screen parent, GameOptions gameOptions, Text text)
{
super(parent, game_options, text);
super(parent, gameOptions, text);
}
@Redirect(method = "init", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/options/ControlsOptionsScreen;addButton(Lnet/minecraft/client/gui/widget/AbstractButtonWidget;)Lnet/minecraft/client/gui/widget/AbstractButtonWidget;", ordinal = 1))
private AbstractButtonWidget on_init(ControlsOptionsScreen screen, AbstractButtonWidget btn)
{
if (this.parent instanceof LambdaControlsControlsScreen)
if (this.parent instanceof ControllerControlsScreen)
return this.addButton(btn);
else
return this.addButton(new ButtonWidget(btn.x, btn.y, btn.getWidth(), ((AbstractButtonWidgetAccessor) btn).lambdacontrols_get_height(), I18n.translate("menu.options"),
return this.addButton(new ButtonWidget(btn.x, btn.y, btn.getWidth(), ((AbstractButtonWidgetAccessor) btn).lambdacontrols_getHeight(), I18n.translate("menu.options"),
b -> this.minecraft.openScreen(new LambdaControlsSettingsScreen(this, this.gameOptions, true))));
}
}

View File

@@ -10,8 +10,10 @@
package me.lambdaurora.lambdacontrols.client.mixin;
import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen;
import net.minecraft.container.Slot;
import net.minecraft.item.ItemGroup;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import org.spongepowered.asm.mixin.gen.Invoker;
@@ -28,7 +30,7 @@ public interface CreativeInventoryScreenAccessor
* @return The selected tab index.
*/
@Accessor("selectedTab")
int lambdacontrols_get_selected_tab();
int lambdacontrols_getSelectedTab();
/**
* Sets the selected tab.
@@ -36,5 +38,14 @@ public interface CreativeInventoryScreenAccessor
* @param group The tab's item group.
*/
@Invoker("setSelectedTab")
void lambdacontrols_set_selected_tab(@NotNull ItemGroup group);
void lambdacontrols_setSelectedTab(@NotNull ItemGroup group);
/**
* Returns whether the slot belongs to the creative inventory or not.
*
* @param slot The slot to check.
* @return True if the slot is from the creative inventory, else false.
*/
@Invoker("isCreativeInventorySlot")
boolean lambdacontrols_isCreativeInventorySlot(@Nullable Slot slot);
}

View File

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

View File

@@ -28,9 +28,9 @@ public class GameRendererMixin
private MinecraftClient client;
@Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Mouse;getX()D"))
private void on_render(float tick_delta, long start_time, boolean full_render, CallbackInfo ci)
private void onRender(float tickDelta, long startTime, boolean fullRender, CallbackInfo ci)
{
if (this.client.currentScreen != null && LambdaControlsClient.get().config.get_controls_mode() == ControlsMode.CONTROLLER)
LambdaControlsClient.get().input.on_pre_render_screen(this.client, this.client.currentScreen);
if (this.client.currentScreen != null && LambdaControlsClient.get().config.getControlsMode() == ControlsMode.CONTROLLER)
LambdaControlsClient.get().input.onPreRenderScreen(this.client, this.client.currentScreen);
}
}

View File

@@ -12,7 +12,6 @@ package me.lambdaurora.lambdacontrols.client.mixin;
import me.lambdaurora.lambdacontrols.client.util.KeyBindingAccessor;
import net.minecraft.client.options.KeyBinding;
import net.minecraft.client.util.InputUtil;
import org.jetbrains.annotations.NotNull;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@@ -28,20 +27,14 @@ public class KeyBindingMixin implements KeyBindingAccessor
@Shadow
private boolean pressed;
@Override
public @NotNull InputUtil.KeyCode get_key_code()
{
return this.keyCode;
}
@Override
public boolean lambdacontrols_press()
{
boolean old_pressed = this.pressed;
boolean oldPressed = this.pressed;
if (!this.pressed)
this.pressed = true;
++this.timesPressed;
return old_pressed != this.pressed;
return oldPressed != this.pressed;
}
@Override

View File

@@ -9,9 +9,8 @@
package me.lambdaurora.lambdacontrols.client.mixin;
import me.lambdaurora.lambdacontrols.ControlsMode;
import me.lambdaurora.lambdacontrols.LambdaControlsFeature;
import me.lambdaurora.lambdacontrols.client.LambdaControlsClient;
import me.lambdaurora.lambdacontrols.client.gui.TouchscreenOverlay;
import net.minecraft.block.BlockState;
import net.minecraft.block.FluidBlock;
import net.minecraft.client.MinecraftClient;
@@ -19,7 +18,6 @@ import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.client.network.ClientPlayerInteractionManager;
import net.minecraft.client.render.GameRenderer;
import net.minecraft.client.util.Window;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.item.BlockItem;
import net.minecraft.item.ItemStack;
@@ -42,16 +40,6 @@ import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
@Mixin(MinecraftClient.class)
public abstract class MinecraftClientMixin
{
@Final
@Shadow
private Window window;
@Shadow
public boolean skipGameRender;
@Shadow
public Screen currentScreen;
@Shadow
@Nullable
public HitResult crosshairTarget;
@@ -73,64 +61,49 @@ public abstract class MinecraftClientMixin
public GameRenderer gameRenderer;
@Inject(method = "<init>", at = @At("RETURN"))
private void lambdacontrols_on_init(CallbackInfo ci)
private void lambdacontrols_onInit(CallbackInfo ci)
{
LambdaControlsClient.get().on_mc_init((MinecraftClient) (Object) this);
LambdaControlsClient.get().onMcInit((MinecraftClient) (Object) this);
}
@Inject(method = "render", at = @At("HEAD"))
private void lambdacontrols_on_render(boolean full_render, CallbackInfo ci)
private void lambdacontrols_onRender(boolean fullRender, CallbackInfo ci)
{
LambdaControlsClient.get().on_render((MinecraftClient) (Object) (this));
LambdaControlsClient.get().onRender((MinecraftClient) (Object) (this));
}
@Inject(method = "tick", at = @At("HEAD"))
private void lambdacontrols_on_handle_input_events(CallbackInfo ci)
@Inject(method = "disconnect(Lnet/minecraft/client/gui/screen/Screen;)V", at = @At("RETURN"))
private void lambdacontrols_onLeave(@Nullable Screen screen, CallbackInfo ci)
{
LambdaControlsClient.get().on_tick((MinecraftClient) (Object) this);
}
@Inject(method = "openScreen", at = @At("RETURN"))
private void lambdacontrols_on_open_screen(@Nullable Screen screen, CallbackInfo ci)
{
LambdaControlsClient mod = LambdaControlsClient.get();
if (screen == null && mod.config.get_controls_mode() == ControlsMode.TOUCHSCREEN) {
screen = new TouchscreenOverlay(mod);
screen.init(((MinecraftClient) (Object) this), this.window.getScaledWidth(), this.window.getScaledHeight());
this.skipGameRender = false;
this.currentScreen = screen;
} else if (screen != null) {
mod.input.on_screen_open(((MinecraftClient) (Object) this), this.window.getWidth(), this.window.getHeight());
}
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)
private void lambdacontrols_on_item_use(CallbackInfo ci, Hand[] hands, int hand_count, int hand_index, Hand hand, ItemStack stack_in_hand)
private void lambdacontrols_onItemUse(CallbackInfo ci, Hand[] hands, int handCount, int handIndex, Hand hand, ItemStack stackInHand)
{
LambdaControlsClient mod = LambdaControlsClient.get();
if (!stack_in_hand.isEmpty() && this.player.pitch > 35.0F && mod.config.has_front_block_placing()) {
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 (!stack_in_hand.isEmpty() && stack_in_hand.getItem() instanceof BlockItem) {
BlockPos player_pos = this.player.getBlockPos().down();
BlockPos target_pos = new BlockPos(this.crosshairTarget.getPos()).subtract(player_pos);
BlockPos vector = new BlockPos(MathHelper.clamp(target_pos.getX(), -1, 1), 0, MathHelper.clamp(target_pos.getZ(), -1, 1));
BlockPos block_pos = player_pos.add(vector);
if (!stackInHand.isEmpty() && stackInHand.getItem() instanceof BlockItem) {
BlockPos playerPos = this.player.getBlockPos().down();
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();
BlockState adjacent_block_state = this.world.getBlockState(block_pos.offset(direction.getOpposite()));
if (adjacent_block_state.isAir() || adjacent_block_state.getBlock() instanceof FluidBlock || (vector.getX() == 0 && vector.getZ() == 0)) {
BlockState adjacentBlockState = this.world.getBlockState(blockPos.offset(direction.getOpposite()));
if (adjacentBlockState.isAir() || adjacentBlockState.getBlock() instanceof FluidBlock || (vector.getX() == 0 && vector.getZ() == 0)) {
return;
}
BlockHitResult hit_result = new BlockHitResult(this.crosshairTarget.getPos(), direction.getOpposite(), block_pos, false);
BlockHitResult hitResult = new BlockHitResult(this.crosshairTarget.getPos(), direction.getOpposite(), blockPos, false);
int previous_stack_count = stack_in_hand.getCount();
ActionResult result = this.interactionManager.interactBlock(this.player, this.world, hand, hit_result);
int previousStackCount = stackInHand.getCount();
ActionResult result = this.interactionManager.interactBlock(this.player, this.world, hand, hitResult);
if (result.isAccepted()) {
if (result.shouldSwingHand()) {
this.player.swingHand(hand);
if (!stack_in_hand.isEmpty() && (stack_in_hand.getCount() != previous_stack_count || this.interactionManager.hasCreativeInventory())) {
if (!stackInHand.isEmpty() && (stackInHand.getCount() != previousStackCount || this.interactionManager.hasCreativeInventory())) {
this.gameRenderer.firstPersonRenderer.resetEquipProgress(hand);
}
}

View File

@@ -32,14 +32,14 @@ public abstract class MouseMixin implements MouseAccessor
protected abstract void onMouseButton(long window, int button, int action, int mods);
@Inject(method = "lockCursor", at = @At("HEAD"), cancellable = true)
private void on_mouse_locked(CallbackInfo ci)
private void lambdacontrols_onMouseLocked(CallbackInfo ci)
{
if (LambdaControlsClient.get().config.get_controls_mode() == ControlsMode.TOUCHSCREEN)
if (LambdaControlsClient.get().config.getControlsMode() == ControlsMode.TOUCHSCREEN)
ci.cancel();
}
@Override
public void lambdacontrols_on_cursor_pos(long window, double x, double y)
public void lambdacontrols_onCursorPos(long window, double x, double y)
{
this.onCursorPos(window, x, y);
}

View File

@@ -11,7 +11,7 @@ package me.lambdaurora.lambdacontrols.client.mixin;
import me.lambdaurora.lambdacontrols.ControlsMode;
import me.lambdaurora.lambdacontrols.client.LambdaControlsClient;
import me.lambdaurora.lambdacontrols.client.gui.LambdaControlsControlsScreen;
import me.lambdaurora.lambdacontrols.client.gui.ControllerControlsScreen;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.screen.SettingsScreen;
import net.minecraft.client.gui.widget.AbstractButtonWidget;
@@ -33,11 +33,11 @@ public class SettingsScreenMixin extends Screen
}
@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))
private AbstractButtonWidget on_init(SettingsScreen screen, AbstractButtonWidget btn)
private AbstractButtonWidget lambdacontrols_onInit(SettingsScreen screen, AbstractButtonWidget btn)
{
if (LambdaControlsClient.get().config.get_controls_mode() == ControlsMode.CONTROLLER) {
return this.addButton(new ButtonWidget(btn.x, btn.y, btn.getWidth(), ((AbstractButtonWidgetAccessor) btn).lambdacontrols_get_height(), btn.getMessage(),
b -> this.minecraft.openScreen(new LambdaControlsControlsScreen(this, false))));
if (LambdaControlsClient.get().config.getControlsMode() == ControlsMode.CONTROLLER) {
return this.addButton(new ButtonWidget(btn.x, btn.y, btn.getWidth(), ((AbstractButtonWidgetAccessor) btn).lambdacontrols_getHeight(), btn.getMessage(),
b -> this.minecraft.openScreen(new ControllerControlsScreen(this, false))));
} else {
return this.addButton(btn);
}

View File

@@ -14,21 +14,21 @@ import net.minecraft.container.Slot;
/**
* Represents an accessor to AbstractContainerScreen.
*/
public interface AbstractContainerScreenAccessor
public interface ContainerScreenAccessor
{
/**
* Gets the left coordinate of the GUI.
*
* @return The left coordinate of the GUI.
*/
int lambdacontrols_get_x();
int lambdacontrols_getX();
/**
* Gets the top coordinate of the GUI.
*
* @return The top coordinate of the GUI.
*/
int lambdacontrols_get_y();
int lambdacontrols_getY();
/**
* Gets the slot at position.
@@ -37,5 +37,5 @@ public interface AbstractContainerScreenAccessor
* @param pos_y The Y position to check.
* @return The slot at the specified position.
*/
Slot lambdacontrols_get_slot_at(double pos_x, double pos_y);
Slot lambdacontrols_getSlotAt(double pos_x, double pos_y);
}

View File

@@ -9,21 +9,16 @@
package me.lambdaurora.lambdacontrols.client.util;
import net.minecraft.client.util.InputUtil;
import org.jetbrains.annotations.NotNull;
/**
* Represents a Minecraft keybinding with extra access.
*/
public interface KeyBindingAccessor
{
@NotNull InputUtil.KeyCode get_key_code();
boolean lambdacontrols_press();
boolean lambdacontrols_unpress();
default boolean handle_press_state(boolean pressed)
default boolean lambdacontrols_handlePressState(boolean pressed)
{
if (pressed)
return this.lambdacontrols_press();

View File

@@ -14,5 +14,5 @@ package me.lambdaurora.lambdacontrols.client.util;
*/
public interface MouseAccessor
{
void lambdacontrols_on_cursor_pos(long window, double x, double y);
void lambdacontrols_onCursorPos(long window, double x, double y);
}

View File

@@ -25,11 +25,11 @@ import org.jetbrains.annotations.NotNull;
@FunctionalInterface
public interface PlayerChangeControlsModeCallback
{
Event<PlayerChangeControlsModeCallback> EVENT = EventFactory.createArrayBacked(PlayerChangeControlsModeCallback.class, listeners -> (player, controls_mode) -> {
Event<PlayerChangeControlsModeCallback> EVENT = EventFactory.createArrayBacked(PlayerChangeControlsModeCallback.class, listeners -> (player, controlsMode) -> {
for (PlayerChangeControlsModeCallback event : listeners) {
event.apply(player, controls_mode);
event.apply(player, controlsMode);
}
});
void apply(@NotNull PlayerEntity player, @NotNull ControlsMode controls_mode);
void apply(@NotNull PlayerEntity player, @NotNull ControlsMode controlsMode);
}

View File

@@ -80,6 +80,7 @@
"lambdacontrols.menu.controls_mode": "Mode",
"lambdacontrols.menu.dead_zone": "Dead Zone",
"lambdacontrols.menu.fly_drifting": "Fly Drifting",
"lambdacontrols.menu.fly_drifting_vertical": "Vertical Fly Drifting",
"lambdacontrols.menu.front_block_placing": "Front Block Placing",
"lambdacontrols.menu.hud_enable": "Enable HUD",
"lambdacontrols.menu.hud_side": "HUD Side",
@@ -105,6 +106,7 @@
"lambdacontrols.tooltip.controls_mode": "The controls mode.",
"lambdacontrols.tooltip.dead_zone": "The dead zone for the controller's analogue sticks.",
"lambdacontrols.tooltip.fly_drifting": "While flying, enables drifting/inertia.",
"lambdacontrols.tooltip.fly_drifting_vertical": "While flying, enables vertical drifting/intertia.",
"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_side": "The position of the HUD.",

View File

@@ -80,6 +80,7 @@
"lambdacontrols.menu.controls_mode": "Mode",
"lambdacontrols.menu.dead_zone": "Zone morte",
"lambdacontrols.menu.fly_drifting": "Inertie de vol",
"lambdacontrols.menu.fly_drifting_vertical": "Inertie verticale de vol",
"lambdacontrols.menu.front_block_placing": "Placement avant de bloc",
"lambdacontrols.menu.hud_enable": "Activer le HUD",
"lambdacontrols.menu.hud_side": "Côté du HUD",
@@ -105,6 +106,7 @@
"lambdacontrols.tooltip.controls_mode": "Change le mode de contrôle.",
"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_vertical": "Pendant que le joueur vole, active le glissement vertical.",
"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_side": "Change la position du HUD.",

View File

@@ -80,6 +80,7 @@
"lambdacontrols.menu.controls_mode": "Mode",
"lambdacontrols.menu.dead_zone": "Zone morte",
"lambdacontrols.menu.fly_drifting": "Inertie de vol",
"lambdacontrols.menu.fly_drifting_vertical": "Inertie verticale de vol",
"lambdacontrols.menu.front_block_placing": "Placement avant de bloc",
"lambdacontrols.menu.hud_enable": "Activer le HUD",
"lambdacontrols.menu.hud_side": "Côté du HUD",
@@ -105,6 +106,7 @@
"lambdacontrols.tooltip.controls_mode": "Change le mode de contrôle.",
"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_vertical": "Pendant que le joueur vole, active le glissement vertical.",
"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_side": "Change la position du HUD.",

View File

@@ -15,8 +15,12 @@ auto_switch_mode = false
[gameplay]
# Enables front block placing like in Bedrock Edition.
front_block_placing = false
# Enables fly drifting.
fly_drifting = false
# Fly behaviors
[gameplay.fly]
# Enables fly drifting.
drifting = false
# Enables vertical fly drifting.
vertical_drifting = true
# Controller settings
[controller]
@@ -58,20 +62,36 @@ auto_switch_mode = false
inventory = "3"
# Jump control.
jump = "0"
# Left movement control.
left = "200"
# Pause game control.
pause_game = "7"
# Pick block control.
pick_block = "14"
# Show player list control.
player_list = "6"
# Right movement control.
right = "100"
# Take screenshot control.
screenshot = "11+0"
# Down slot control.
slot_down = "13"
# Left slot control.
slot_left = "14"
# Right slot control.
slot_right = "12"
# Up slot control.
slot_up = "11"
# Sneak control.
sneak = "10"
# Sprint control.
sprint = "9"
# Swap hands control.
swap_hands = "2"
# Switch to left tab control.
tab_left = "4"
# Switch to right tab control.
tab_right = "5"
# Toggle perspective control.
toggle_perspective = "11+3"
# Toggle smooth camera control.

View File

@@ -33,7 +33,7 @@
"fabricloader": ">=0.4.0",
"fabric": "*",
"minecraft": "1.15.x",
"spruceui": ">=1.1.0"
"spruceui": ">=1.3.4"
},
"recommends": {
"modmenu": ">=1.8.0+build.16",

View File

@@ -4,8 +4,10 @@
"compatibilityLevel": "JAVA_8",
"client": [
"AbstractButtonWidgetAccessor",
"AbstractContainerScreenMixin",
"AdvancementsScreenAccessor",
"ContainerScreenMixin",
"ClientPlayerEntityMixin",
"ClientPlayNetworkHandlerMixin",
"ControlsOptionsScreenMixin",
"CreativeInventoryScreenAccessor",
"EntryListWidgetAccessor",

View File

@@ -3,17 +3,17 @@ org.gradle.jvmargs=-Xmx1G
# Fabric Properties
# check these on https://fabricmc.net/use
minecraft_version=1.15.1
yarn_mappings=1.15.1+build.37:v2
loader_version=0.7.3+build.176
minecraft_version=1.15.2
yarn_mappings=1.15.2+build.9:v2
loader_version=0.7.6+build.180
# Mod Properties
mod_version = 1.1.0-test9
mod_version = 1.1.0
maven_group = me.lambdaurora
archives_base_name = lambdacontrols
# Dependencies
# currently not on the main fabric site, check on the maven: https://maven.fabricmc.net/net/fabricmc/fabric-api/fabric-api
fabric_version=0.4.27+build.286-1.15
spruceui_version=1.1.0
fabric_version=0.4.29+build.290-1.15
spruceui_version=1.3.4

View File

@@ -10,4 +10,4 @@ pluginManagement {
}
rootProject.name = 'lambdacontrols'
include 'core', 'fabric', 'elytra'
include 'core', 'fabric', 'spigot'

50
spigot/build.gradle Normal file
View File

@@ -0,0 +1,50 @@
plugins {
id 'java-library'
}
archivesBaseName = project.archives_base_name + "-spigot"
repositories {
maven { url = 'https://hub.spigotmc.org/nexus/content/groups/public/' }
maven { url = 'https://libraries.minecraft.net/' }
}
configurations {
include
}
dependencies {
api project(":core")
include(project(":core")) {
exclude group: 'com.google.code.gson'
exclude group: 'com.google.guava'
}
api 'org.spigotmc:spigot-api:1.15.1-R0.1-SNAPSHOT'
api 'io.netty:netty-all:4.1.28.Final'
}
processResources {
inputs.property "version", project.version
from(sourceSets.main.resources.srcDirs) {
include "plugin.yml"
expand 'version': project.version.toString().replace("#", "")
}
}
jar {
from '../LICENSE'
dependsOn configurations.include
from {
(configurations.include).collect {
it.isDirectory() ? it : zipTree(it)
}
}
}
java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}

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;
import com.electronwill.nightconfig.core.file.FileConfig;
import org.jetbrains.annotations.NotNull;
import java.io.File;
/**
* Represents the LambdaControls Spigot configuration.
*/
public class LambdaControlsConfig
{
private static final boolean DEFAULT_FRONT_BLOCK_PLACING = true;
protected final FileConfig config = FileConfig.builder("config/lambdacontrols.toml").concurrent().defaultResource("/server_config.toml").build();
private final LambdaControlsSpigot plugin;
public LambdaControlsConfig(@NotNull LambdaControlsSpigot plugin)
{
this.plugin = plugin;
}
public void load()
{
File configDir = new File("config/");
if (!configDir.exists())
configDir.mkdirs();
this.config.load();
this.plugin.log("Configuration loaded.");
LambdaControlsFeature.FRONT_BLOCK_PLACING.setAllowed(this.config.getOrElse("gameplay.front_block_placing", DEFAULT_FRONT_BLOCK_PLACING));
}
}

View File

@@ -0,0 +1,148 @@
/*
* 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;
import io.netty.buffer.Unpooled;
import me.lambdaurora.lambdacontrols.event.PlayerChangeControlsModeEvent;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.plugin.messaging.PluginMessageListener;
import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import static me.lambdaurora.lambdacontrols.LambdaControlsConstants.*;
/**
* Represents the LambdaControls spigot plugin which provides extra features for servers.
*
* @author LambdAurora
* @version 1.1.0
* @since 1.1.0
*/
public class LambdaControlsSpigot extends JavaPlugin implements PluginMessageListener, Listener
{
private static final Map<Player, ControlsMode> PLAYERS_CONTROLS_MODE = new HashMap<>();
public final LambdaControlsConfig config = new LambdaControlsConfig(this);
@Override
public void onEnable()
{
super.onEnable();
this.config.load();
// Note that Spigot has a bullshit channel size restriction as Minecraft SUPPORTS UP TO 32767 AS CHANNEL SIZE.
// Please stop using that bad server software, move over Sponge or idk other things. REALLY.
this.getServer().getMessenger().registerIncomingPluginChannel(this, CONTROLS_MODE_CHANNEL.toString(), this);
this.getServer().getMessenger().registerOutgoingPluginChannel(this, CONTROLS_MODE_CHANNEL.toString());
this.getServer().getMessenger().registerOutgoingPluginChannel(this, FEATURE_CHANNEL.toString());
this.getServer().getMessenger().registerIncomingPluginChannel(this, HELLO_CHANNEL.toString(), this);
this.getServer().getPluginManager().registerEvents(this, this);
this.getServer().getOnlinePlayers().forEach(player -> {
PLAYERS_CONTROLS_MODE.put(player, ControlsMode.DEFAULT);
this.requestPlayerControlsMode(player);
this.updatePlayerFeature(player, LambdaControlsFeature.FRONT_BLOCK_PLACING);
});
}
@Override
public void onDisable()
{
super.onDisable();
this.getServer().getMessenger().unregisterIncomingPluginChannel(this, CONTROLS_MODE_CHANNEL.toString());
this.getServer().getMessenger().unregisterOutgoingPluginChannel(this, CONTROLS_MODE_CHANNEL.toString());
this.getServer().getMessenger().unregisterOutgoingPluginChannel(this, FEATURE_CHANNEL.toString());
this.getServer().getMessenger().unregisterIncomingPluginChannel(this, HELLO_CHANNEL.toString());
PLAYERS_CONTROLS_MODE.clear();
}
public void requestPlayerControlsMode(@NotNull Player player)
{
player.sendPluginMessage(this, CONTROLS_MODE_CHANNEL.toString(), new byte[0]);
}
public void updatePlayerFeature(@NotNull Player player, @NotNull LambdaControlsFeature feature)
{
Objects.requireNonNull(player);
Objects.requireNonNull(feature);
player.sendPluginMessage(this, FEATURE_CHANNEL.toString(), this.makeFeatureMessage(feature));
}
/**
* Prints a message to the terminal.
*
* @param info The message to print.
*/
public void log(String info)
{
this.getLogger().info(info);
}
@Override
public void onPluginMessageReceived(@NotNull String channel, @NotNull Player player, @NotNull byte[] message)
{
if (channel.equals(HELLO_CHANNEL.toString())) {
NettyPacketBuffer buffer = new NettyPacketBuffer(Unpooled.copiedBuffer(message));
String version = buffer.readString(16);
ControlsMode.byId(buffer.readString(32)).ifPresent(controlsMode -> {
PLAYERS_CONTROLS_MODE.put(player, controlsMode);
PlayerChangeControlsModeEvent event = new PlayerChangeControlsModeEvent(player, controlsMode);
this.getServer().getPluginManager().callEvent(event);
});
this.updatePlayerFeature(player, LambdaControlsFeature.FRONT_BLOCK_PLACING);
} else if (channel.equals(CONTROLS_MODE_CHANNEL.toString())) {
NettyPacketBuffer buffer = new NettyPacketBuffer(Unpooled.copiedBuffer(message));
ControlsMode.byId(buffer.readString(32)).ifPresent(controlsMode -> {
PLAYERS_CONTROLS_MODE.put(player, controlsMode);
PlayerChangeControlsModeEvent event = new PlayerChangeControlsModeEvent(player, controlsMode);
this.getServer().getPluginManager().callEvent(event);
});
}
}
/**
* Returns a packet byte buffer made for the lambdacontrols:feature plugin message.
*
* @param feature The feature data to send.
* @return The packet byte buffer.
*/
public byte[] makeFeatureMessage(@NotNull LambdaControlsFeature feature)
{
Objects.requireNonNull(feature, "Feature cannot be null.");
NettyPacketBuffer buffer = new NettyPacketBuffer(Unpooled.buffer());
buffer.writeString(feature.getName());
buffer.writeBoolean(feature.isAllowed());
return buffer.array();
}
@EventHandler
public void onPlayerJoin(@NotNull PlayerJoinEvent event)
{
PLAYERS_CONTROLS_MODE.put(event.getPlayer(), ControlsMode.DEFAULT);
}
@EventHandler
public void onPlayerLeave(@NotNull PlayerQuitEvent event)
{
PLAYERS_CONTROLS_MODE.remove(event.getPlayer());
}
}

View File

@@ -0,0 +1,102 @@
package me.lambdaurora.lambdacontrols;
import io.netty.buffer.ByteBuf;
import io.netty.handler.codec.DecoderException;
import io.netty.handler.codec.EncoderException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
public class NettyPacketBuffer extends PacketBuffer
{
public NettyPacketBuffer(ByteBuf byteBuf)
{
super(byteBuf);
}
@Override
public int readVarint()
{
int var1 = 0;
int var2 = 0;
byte var3;
do {
var3 = this.readByte();
var1 |= (var3 & 127) << var2++ * 7;
if (var2 > 5)
throw new RuntimeException("VarInt too big");
} while ((var3 & 128) == 128);
return var1;
}
@Override
public void writeVarint(int input)
{
while ((input & -128) != 0) {
this.writeByte(input & 127 | 128);
input >>>= 7;
}
this.writeByte(input);
}
@Override
public String readString(int maxLength)
{
int var2 = this.readVarint();
if (var2 > maxLength * 4)
throw new DecoderException("The received encoded string buffer length is longer than maximum allowed (" + var2 + " > " + maxLength * 4 + ")");
else if (var2 < 0)
throw new DecoderException("The received encoded string buffer length is less than zero! Weird string!");
else {
String var3 = this.readCharSequence(var2, StandardCharsets.UTF_8).toString();
if (var3.length() > maxLength)
throw new DecoderException("The received string length is longer than maximum allowed (" + var2 + " > " + maxLength + ")");
else
return var3;
}
}
@Override
public void writeString(String string)
{
byte[] var2 = string.getBytes(Charset.forName("UTF-8"));
if (var2.length > 32767) {
throw new EncoderException("String too big (was " + string.length() + " data encoded, max " + 32767 + ")");
} else {
this.writeVarint(var2.length);
this.writeCharSequence(string, StandardCharsets.UTF_8);
}
}
@Override
public boolean equals(Object o)
{
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
NettyPacketBuffer buffer = (NettyPacketBuffer) o;
return byteBuf.equals(buffer.byteBuf);
}
@Override
public int compareTo(ByteBuf buffer)
{
return this.byteBuf.compareTo(buffer);
}
@Override
public String toString()
{
return this.byteBuf.toString();
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,65 @@
/*
* 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.event;
import me.lambdaurora.lambdacontrols.ControlsMode;
import org.bukkit.entity.Player;
import org.bukkit.event.HandlerList;
import org.bukkit.event.player.PlayerEvent;
import org.jetbrains.annotations.NotNull;
/**
* Represents an event which is fired when a player change their controls mode.
*
* @author LambdAurora
* @version 1.1.0
* @since 1.1.0
*/
public class PlayerChangeControlsModeEvent extends PlayerEvent
{
private static final HandlerList HANDLERS = new HandlerList();
private final ControlsMode controlsMode;
public PlayerChangeControlsModeEvent(@NotNull Player who, @NotNull ControlsMode controlsMode)
{
super(who);
this.controlsMode = controlsMode;
}
/**
* Returns the controls mode of the player.
*
* @return The player's controls mode.
*/
public ControlsMode getControlsMode()
{
return this.controlsMode;
}
@Override
public String toString()
{
return "PlayerChangeControlsModeEvent{" +
"player=" + this.player +
", controls_mode=" + this.controlsMode +
'}';
}
@Override
public @NotNull HandlerList getHandlers()
{
return HANDLERS;
}
public static @NotNull HandlerList getHandlerList()
{
return HANDLERS;
}
}

View File

@@ -0,0 +1,6 @@
name: LambdaControls
version: ${version}
description: A quick Spigot plugin for LambdaControls which allow server admins to disable some features.
main: me.lambdaurora.lambdacontrols.LambdaControlsSpigot
api-version: 1.13

View File

@@ -0,0 +1,6 @@
# LambdaControls server configuration.
# Gameplay settings
[gameplay]
# Allows front block placing like in Bedrock Edition.
front_block_placing = true