mirror of
https://github.com/TeamMidnightDust/MidnightControls.git
synced 2025-12-13 23:25:10 +01:00
✨ Use GLFW gamepad instead of joystick.
This commit is contained in:
188
src/main/java/me/lambdaurora/lambdacontrols/Controller.java
Normal file
188
src/main/java/me/lambdaurora/lambdacontrols/Controller.java
Normal file
@@ -0,0 +1,188 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2019 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 org.lwjgl.BufferUtils;
|
||||||
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
import org.lwjgl.glfw.GLFWGamepadState;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.channels.Channels;
|
||||||
|
import java.nio.channels.ReadableByteChannel;
|
||||||
|
import java.nio.channels.SeekableByteChannel;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import static org.lwjgl.BufferUtils.createByteBuffer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a controller.
|
||||||
|
*/
|
||||||
|
public class Controller implements Nameable
|
||||||
|
{
|
||||||
|
private static final Map<Integer, Controller> CONTROLLERS = new HashMap<>();
|
||||||
|
private final int id;
|
||||||
|
|
||||||
|
public Controller(int id)
|
||||||
|
{
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the identifier of this controller.
|
||||||
|
*
|
||||||
|
* @return The identifier of this controller.
|
||||||
|
*/
|
||||||
|
public int get_id()
|
||||||
|
{
|
||||||
|
return this.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the controller's globally unique identifier.
|
||||||
|
*
|
||||||
|
* @return The controller's GUID.
|
||||||
|
*/
|
||||||
|
public String get_guid()
|
||||||
|
{
|
||||||
|
String guid = GLFW.glfwGetJoystickGUID(this.id);
|
||||||
|
return guid == null ? "" : guid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether this controller is connected or not.
|
||||||
|
*
|
||||||
|
* @return True if this controller is connected, else false.
|
||||||
|
*/
|
||||||
|
public boolean is_connected()
|
||||||
|
{
|
||||||
|
return GLFW.glfwJoystickPresent(this.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether this controller is a gamepad or not.
|
||||||
|
*
|
||||||
|
* @return True if this controller is a gamepad, else false.
|
||||||
|
*/
|
||||||
|
public boolean is_gamepad()
|
||||||
|
{
|
||||||
|
return GLFW.glfwJoystickIsGamepad(this.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the name of the controller.
|
||||||
|
*
|
||||||
|
* @return The controller's name.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public @NotNull String get_name()
|
||||||
|
{
|
||||||
|
String name = this.is_gamepad() ? GLFW.glfwGetGamepadName(this.id) : GLFW.glfwGetJoystickName(this.id);
|
||||||
|
return name == null ? "" : name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the state of the controller.
|
||||||
|
*
|
||||||
|
* @return The state of the controller input.
|
||||||
|
*/
|
||||||
|
public GLFWGamepadState get_state()
|
||||||
|
{
|
||||||
|
GLFWGamepadState state = GLFWGamepadState.create();
|
||||||
|
if (this.is_gamepad())
|
||||||
|
GLFW.glfwGetGamepadState(this.id, state);
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static @NotNull Controller by_id(int id)
|
||||||
|
{
|
||||||
|
if (id > GLFW.GLFW_JOYSTICK_LAST) {
|
||||||
|
LambdaControls.get().log("Controller '" + id + "' doesn't exist.");
|
||||||
|
id = GLFW.GLFW_JOYSTICK_LAST;
|
||||||
|
}
|
||||||
|
Controller controller;
|
||||||
|
if (CONTROLLERS.containsKey(id))
|
||||||
|
return CONTROLLERS.get(id);
|
||||||
|
else {
|
||||||
|
controller = new Controller(id);
|
||||||
|
CONTROLLERS.put(id, controller);
|
||||||
|
return controller;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static @NotNull Optional<Controller> by_guid(@NotNull String guid)
|
||||||
|
{
|
||||||
|
return CONTROLLERS.values().stream().filter(Controller::is_connected)
|
||||||
|
.filter(controller -> controller.get_guid().equals(guid))
|
||||||
|
.findFirst();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ByteBuffer resizeBuffer(ByteBuffer buffer, int new_capacity)
|
||||||
|
{
|
||||||
|
ByteBuffer newBuffer = BufferUtils.createByteBuffer(new_capacity);
|
||||||
|
buffer.flip();
|
||||||
|
newBuffer.put(buffer);
|
||||||
|
return newBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
* @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
|
||||||
|
{
|
||||||
|
ByteBuffer buffer = null;
|
||||||
|
|
||||||
|
Path path = Paths.get(resource);
|
||||||
|
if (Files.isReadable(path)) {
|
||||||
|
try (SeekableByteChannel fc = Files.newByteChannel(path)) {
|
||||||
|
buffer = createByteBuffer((int) fc.size() + 2);
|
||||||
|
while (fc.read(buffer) != -1) {
|
||||||
|
;
|
||||||
|
}
|
||||||
|
buffer.put((byte) 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer.flip();
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the controller mappings.
|
||||||
|
*/
|
||||||
|
public static void update_mappings()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
File mappings_file = new File("config/gamecontrollerdb.txt");
|
||||||
|
if (!mappings_file.exists())
|
||||||
|
return;
|
||||||
|
ByteBuffer buffer = io_resource_to_buffer(mappings_file.getPath(), 1024);
|
||||||
|
//buffer.rewind();
|
||||||
|
System.out.println(buffer);
|
||||||
|
GLFW.glfwUpdateGamepadMappings(buffer);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
package me.lambdaurora.lambdacontrols;
|
package me.lambdaurora.lambdacontrols;
|
||||||
|
|
||||||
import me.lambdaurora.lambdacontrols.mixin.AbstractContainerScreenAccessor;
|
import me.lambdaurora.lambdacontrols.util.AbstractContainerScreenAccessor;
|
||||||
import me.lambdaurora.lambdacontrols.util.CreativeInventoryScreenAccessor;
|
import me.lambdaurora.lambdacontrols.util.CreativeInventoryScreenAccessor;
|
||||||
import me.lambdaurora.lambdacontrols.util.LambdaKeyBinding;
|
import me.lambdaurora.lambdacontrols.util.LambdaKeyBinding;
|
||||||
import me.lambdaurora.lambdacontrols.util.MouseAccessor;
|
import me.lambdaurora.lambdacontrols.util.MouseAccessor;
|
||||||
@@ -17,18 +17,21 @@ import net.minecraft.client.MinecraftClient;
|
|||||||
import net.minecraft.client.gui.Element;
|
import net.minecraft.client.gui.Element;
|
||||||
import net.minecraft.client.gui.ParentElement;
|
import net.minecraft.client.gui.ParentElement;
|
||||||
import net.minecraft.client.gui.screen.Screen;
|
import net.minecraft.client.gui.screen.Screen;
|
||||||
import net.minecraft.client.gui.screen.ingame.AbstractContainerScreen;
|
import net.minecraft.client.gui.screen.advancement.AdvancementsScreen;
|
||||||
import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen;
|
import net.minecraft.client.gui.screen.ingame.*;
|
||||||
import net.minecraft.client.gui.screen.world.WorldListWidget;
|
import net.minecraft.client.gui.screen.world.WorldListWidget;
|
||||||
import net.minecraft.client.gui.widget.*;
|
import net.minecraft.client.gui.widget.*;
|
||||||
import net.minecraft.client.options.KeyBinding;
|
import net.minecraft.client.options.KeyBinding;
|
||||||
import net.minecraft.container.Slot;
|
import net.minecraft.container.Slot;
|
||||||
|
import net.minecraft.container.SlotActionType;
|
||||||
import net.minecraft.item.ItemGroup;
|
import net.minecraft.item.ItemGroup;
|
||||||
import net.minecraft.util.math.MathHelper;
|
import net.minecraft.util.math.MathHelper;
|
||||||
import org.aperlambda.lambdacommon.utils.Pair;
|
import org.aperlambda.lambdacommon.utils.Pair;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.lwjgl.glfw.GLFW;
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
import org.lwjgl.glfw.GLFWGamepadState;
|
||||||
|
import org.lwjgl.system.CallbackI;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.FloatBuffer;
|
import java.nio.FloatBuffer;
|
||||||
@@ -41,12 +44,8 @@ public class ControllerInput
|
|||||||
{
|
{
|
||||||
private static final Map<Integer, Boolean> BUTTON_STATES = new HashMap<>();
|
private static final Map<Integer, Boolean> BUTTON_STATES = new HashMap<>();
|
||||||
private static final Map<Integer, Integer> BUTTON_COOLDOWNS = new HashMap<>();
|
private static final Map<Integer, Integer> BUTTON_COOLDOWNS = new HashMap<>();
|
||||||
private static final Map<Integer, Float> AXE_STATES = new HashMap<>();
|
|
||||||
private final LambdaControls mod;
|
|
||||||
private final LambdaControlsConfig config;
|
private final LambdaControlsConfig config;
|
||||||
private int controller = GLFW.GLFW_JOYSTICK_3;
|
|
||||||
private int action_gui_cooldown = 0;
|
private int action_gui_cooldown = 0;
|
||||||
private boolean last_a_state = false;
|
|
||||||
private boolean continuous_sneak = false;
|
private boolean continuous_sneak = false;
|
||||||
private int last_sneak = 0;
|
private int last_sneak = 0;
|
||||||
private double prev_target_yaw = 0.0;
|
private double prev_target_yaw = 0.0;
|
||||||
@@ -64,7 +63,6 @@ public class ControllerInput
|
|||||||
|
|
||||||
public ControllerInput(@NotNull LambdaControls mod)
|
public ControllerInput(@NotNull LambdaControls mod)
|
||||||
{
|
{
|
||||||
this.mod = mod;
|
|
||||||
this.config = mod.config;
|
this.config = mod.config;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,16 +82,26 @@ public class ControllerInput
|
|||||||
--this.action_gui_cooldown;
|
--this.action_gui_cooldown;
|
||||||
this.prev_target_yaw = this.target_yaw;
|
this.prev_target_yaw = this.target_yaw;
|
||||||
this.prev_target_pitch = this.target_pitch;
|
this.prev_target_pitch = this.target_pitch;
|
||||||
this.fetch_button_input(client);
|
this.prev_target_mouse_x = this.target_mouse_x;
|
||||||
this.fetch_axe_input(client);
|
this.prev_target_mouse_y = this.target_mouse_y;
|
||||||
|
|
||||||
|
Controller controller = this.config.get_controller();
|
||||||
|
if (controller.is_connected()) {
|
||||||
|
GLFWGamepadState state = controller.get_state();
|
||||||
|
this.fetch_button_input(client, state);
|
||||||
|
this.fetch_axe_input(client, state);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void on_pre_render_screen(@NotNull MinecraftClient client, @NotNull Screen screen)
|
public void on_pre_render_screen(@NotNull MinecraftClient client, @NotNull Screen screen)
|
||||||
{
|
{
|
||||||
if (this.prev_target_mouse_x != this.target_mouse_x || this.prev_target_mouse_y != this.target_mouse_y) {
|
if (!this.is_screen_interactive(screen)) {
|
||||||
double mouse_x = prev_target_mouse_x + (this.target_mouse_x - this.prev_target_mouse_x) * client.getTickDelta() + 0.5;
|
if (this.prev_target_mouse_x != this.target_mouse_x || this.prev_target_mouse_y != this.target_mouse_y) {
|
||||||
double mouse_y = prev_target_mouse_y + (this.target_mouse_y - this.prev_target_mouse_y) * client.getTickDelta() + 0.5;
|
double mouse_x = this.prev_target_mouse_x + (this.target_mouse_x - this.prev_target_mouse_x) * client.getTickDelta() + 0.5;
|
||||||
GLFW.glfwSetCursorPos(client.window.getHandle(), mouse_x, mouse_y);
|
double mouse_y = this.prev_target_mouse_y + (this.target_mouse_y - this.prev_target_mouse_y) * client.getTickDelta() + 0.5;
|
||||||
|
GLFW.glfwSetCursorPos(client.window.getHandle(), mouse_x, mouse_y);
|
||||||
|
((MouseAccessor) client.mouse).on_cursor_pos(client.window.getHandle(), mouse_x, mouse_y);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,48 +121,43 @@ public class ControllerInput
|
|||||||
public void on_screen_open(@NotNull MinecraftClient client, int window_width, int window_height)
|
public void on_screen_open(@NotNull MinecraftClient client, int window_width, int window_height)
|
||||||
{
|
{
|
||||||
if (client.currentScreen == null) {
|
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_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.target_mouse_y = this.prev_target_mouse_y = (int) (window_height / 2.F);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void fetch_button_input(@NotNull MinecraftClient client)
|
private void fetch_button_input(@NotNull MinecraftClient client, @NotNull GLFWGamepadState gamepad_state)
|
||||||
{
|
{
|
||||||
ByteBuffer buffer = GLFW.glfwGetJoystickButtons(this.controller);
|
ByteBuffer buffer = gamepad_state.buttons();
|
||||||
if (buffer != null) {
|
for (int i = 0; i < buffer.limit(); i++) {
|
||||||
for (int i = 0; i < buffer.limit(); i++) {
|
boolean btn_state = buffer.get() == (byte) 1;
|
||||||
boolean btn_state = buffer.get() == (byte) 1;
|
boolean previous_state = BUTTON_STATES.getOrDefault(i, false);
|
||||||
boolean previous_state = BUTTON_STATES.getOrDefault(i, false);
|
|
||||||
|
|
||||||
if (btn_state != previous_state) {
|
if (btn_state != previous_state) {
|
||||||
this.handle_button(client, i, btn_state ? 0 : 1, btn_state);
|
this.handle_button(client, i, btn_state ? 0 : 1, btn_state);
|
||||||
if (btn_state)
|
if (btn_state)
|
||||||
BUTTON_COOLDOWNS.put(i, 5);
|
BUTTON_COOLDOWNS.put(i, 5);
|
||||||
} else if (btn_state) {
|
} else if (btn_state) {
|
||||||
if (BUTTON_COOLDOWNS.getOrDefault(i, 0) == 0) {
|
if (BUTTON_COOLDOWNS.getOrDefault(i, 0) == 0) {
|
||||||
BUTTON_COOLDOWNS.put(i, 5);
|
BUTTON_COOLDOWNS.put(i, 5);
|
||||||
this.handle_button(client, i, 2, true);
|
this.handle_button(client, i, 2, true);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BUTTON_STATES.put(i, btn_state);
|
|
||||||
if (this.config.is_jump_button(i))
|
|
||||||
this.last_a_state = btn_state;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BUTTON_STATES.put(i, btn_state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void fetch_axe_input(@NotNull MinecraftClient client)
|
private void fetch_axe_input(@NotNull MinecraftClient client, @NotNull GLFWGamepadState gamepad_state)
|
||||||
{
|
{
|
||||||
FloatBuffer buffer = GLFW.glfwGetJoystickAxes(this.controller);
|
FloatBuffer buffer = gamepad_state.axes();
|
||||||
if (buffer != null) {
|
for (int i = 0; i < buffer.limit(); i++) {
|
||||||
for (int i = 0; i < buffer.limit(); i++) {
|
float value = buffer.get();
|
||||||
float value = buffer.get();
|
float abs_value = Math.abs(value);
|
||||||
float abs_value = Math.abs(value);
|
|
||||||
|
|
||||||
int state = value > this.config.get_dead_zone() ? 1 : (value < -this.config.get_dead_zone() ? 2 : 0);
|
int state = value > this.config.get_dead_zone() ? 1 : (value < -this.config.get_dead_zone() ? 2 : 0);
|
||||||
this.handle_axe(client, i, value, abs_value, state);
|
this.handle_axe(client, i, value, abs_value, state);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,35 +165,60 @@ public class ControllerInput
|
|||||||
{
|
{
|
||||||
if (action == 0) {
|
if (action == 0) {
|
||||||
// Handles RB and LB buttons.
|
// Handles RB and LB buttons.
|
||||||
if (this.config.is_hotbar_left_button(button) || this.config.is_hotbar_right_button(button)) {
|
if (button == GLFW.GLFW_GAMEPAD_BUTTON_LEFT_BUMPER || button == GLFW.GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER) {
|
||||||
this.handle_rb_lb(client, this.config.is_hotbar_right_button(button));
|
this.handle_rb_lb(client, button == GLFW.GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handles when the player presses the Start button.
|
// Handles when the player presses the Start button.
|
||||||
if (this.config.is_start_button(button)) {
|
if (button == GLFW.GLFW_GAMEPAD_BUTTON_START) {
|
||||||
// If in game, then pause the game.
|
// If in game, then pause the game.
|
||||||
if (client.currentScreen == null)
|
if (client.currentScreen == null)
|
||||||
client.openPauseMenu(false);
|
client.openPauseMenu(false);
|
||||||
else // Else just close the current screen.
|
else if (client.currentScreen instanceof AbstractContainerScreen) // If the current screen is a container then close it.
|
||||||
|
client.player.closeContainer();
|
||||||
|
else// Else just close the current screen.
|
||||||
client.currentScreen.onClose();
|
client.currentScreen.onClose();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.config.is_jump_button(button) && client.currentScreen != null) {
|
if (button == GLFW.GLFW_GAMEPAD_BUTTON_A && client.currentScreen != null) {
|
||||||
if (this.action_gui_cooldown == 0) {
|
if (this.action_gui_cooldown == 0) {
|
||||||
Element focused = client.currentScreen.getFocused();
|
Element focused = client.currentScreen.getFocused();
|
||||||
if (focused != null)
|
if (focused != null && this.is_screen_interactive(client.currentScreen))
|
||||||
this.handle_a_button(focused);
|
this.handle_a_button(focused);
|
||||||
this.action_gui_cooldown = 5; // Prevent to press too quickly the focused element, so we have to skip 5 ticks.
|
this.action_gui_cooldown = 5; // Prevent to press too quickly the focused element, so we have to skip 5 ticks.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (client.currentScreen instanceof AbstractContainerScreen) {
|
||||||
|
double pos_x = client.mouse.getX() * (double) client.window.getScaledWidth() / (double) client.window.getWidth();
|
||||||
|
double pos_y = client.mouse.getY() * (double) client.window.getScaledHeight() / (double) client.window.getHeight();
|
||||||
|
Slot slot = ((AbstractContainerScreenAccessor) client.currentScreen).get_slot_at(pos_x, pos_y);
|
||||||
|
if (button == GLFW.GLFW_GAMEPAD_BUTTON_A && slot != null) {
|
||||||
|
client.interactionManager.method_2906(((AbstractContainerScreen) client.currentScreen).getContainer().syncId, slot.id, GLFW.GLFW_MOUSE_BUTTON_1, SlotActionType.PICKUP, client.player);
|
||||||
|
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.method_2906(((AbstractContainerScreen) 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.method_2906(((AbstractContainerScreen) client.currentScreen).getContainer().syncId, slot.id, GLFW.GLFW_MOUSE_BUTTON_1, SlotActionType.QUICK_MOVE, client.player);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else if (button == GLFW.GLFW_GAMEPAD_BUTTON_B) {
|
||||||
|
if (client.currentScreen != null) {
|
||||||
|
client.currentScreen.onClose();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handles sneak button and continuous sneak.
|
// Handles sneak button and continuous sneak.
|
||||||
if (this.config.is_sneak_button(button) && client.player != null) {
|
if (button == GLFW.GLFW_GAMEPAD_BUTTON_RIGHT_THUMB && client.player != null) {
|
||||||
if (action == 0) {
|
if (action == 0) {
|
||||||
if (this.continuous_sneak) {
|
if (this.continuous_sneak) {
|
||||||
this.set_sneaking(client, this.continuous_sneak = false);
|
this.set_sneaking(client, this.continuous_sneak = false);
|
||||||
@@ -208,17 +236,20 @@ public class ControllerInput
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.config.is_jump_button(button) && client.currentScreen != null) {
|
if (button == GLFW.GLFW_GAMEPAD_BUTTON_A && client.currentScreen != null && !this.is_screen_interactive(client.currentScreen)) {
|
||||||
if (this.last_a_state != state) {
|
double mouse_x = client.mouse.getX() * (double) client.window.getScaledWidth() / (double) client.window.getWidth();
|
||||||
double mouse_x = client.mouse.getX() * (double) client.window.getScaledWidth() / (double) client.window.getWidth();
|
double mouse_y = client.mouse.getY() * (double) client.window.getScaledHeight() / (double) client.window.getHeight();
|
||||||
double mouse_y = client.mouse.getY() * (double) client.window.getScaledHeight() / (double) client.window.getHeight();
|
if (client.currentScreen instanceof AbstractContainerScreen) {
|
||||||
if (state) {
|
Slot slot = ((AbstractContainerScreenAccessor) client.currentScreen).get_slot_at(mouse_x, mouse_y);
|
||||||
client.currentScreen.mouseClicked(mouse_x, mouse_y, GLFW.GLFW_MOUSE_BUTTON_1);
|
if (slot != null)
|
||||||
} else {
|
return;
|
||||||
client.currentScreen.mouseReleased(mouse_x, mouse_y, GLFW.GLFW_MOUSE_BUTTON_1);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
if (action == 0) {
|
||||||
|
client.currentScreen.mouseClicked(mouse_x, mouse_y, GLFW.GLFW_MOUSE_BUTTON_1);
|
||||||
|
} else if (action == 1) {
|
||||||
|
client.currentScreen.mouseReleased(mouse_x, mouse_y, GLFW.GLFW_MOUSE_BUTTON_1);
|
||||||
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (client.currentScreen == null && action != 2) {
|
if (client.currentScreen == null && action != 2) {
|
||||||
@@ -265,7 +296,7 @@ public class ControllerInput
|
|||||||
} else {
|
} else {
|
||||||
boolean allow_mouse_control = true;
|
boolean allow_mouse_control = true;
|
||||||
|
|
||||||
if (this.action_gui_cooldown == 0 && this.config.is_movement_axis(axe)) {
|
if (this.action_gui_cooldown == 0 && this.config.is_movement_axis(axe) && this.is_screen_interactive(client.currentScreen)) {
|
||||||
if (this.config.is_forward_button(axe, false, as_button_state)) {
|
if (this.config.is_forward_button(axe, false, as_button_state)) {
|
||||||
allow_mouse_control = this.change_focus(client.currentScreen, false);
|
allow_mouse_control = this.change_focus(client.currentScreen, false);
|
||||||
} else if (this.config.is_back_button(axe, false, as_button_state)) {
|
} else if (this.config.is_back_button(axe, false, as_button_state)) {
|
||||||
@@ -319,13 +350,13 @@ public class ControllerInput
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (Math.abs(this.mouse_speed_x) > .05F || Math.abs(this.mouse_speed_y) > .05F) {
|
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_rotation_speed();
|
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.window.getWidth());
|
this.target_mouse_x = MathHelper.clamp(this.target_mouse_x, 0, client.window.getWidth());
|
||||||
this.target_mouse_y += this.mouse_speed_y * this.config.get_rotation_speed();
|
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.window.getHeight());
|
this.target_mouse_y = MathHelper.clamp(this.target_mouse_y, 0, client.window.getHeight());
|
||||||
}
|
}
|
||||||
|
|
||||||
//this.move_mouse_to_closest_slot(client, client.currentScreen);
|
this.move_mouse_to_closest_slot(client, client.currentScreen);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.prev_x_axis = movement_x;
|
this.prev_x_axis = movement_x;
|
||||||
@@ -431,6 +462,11 @@ public class ControllerInput
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean is_screen_interactive(@NotNull Screen screen)
|
||||||
|
{
|
||||||
|
return !(screen instanceof AdvancementsScreen || screen instanceof AbstractContainerScreen);
|
||||||
|
}
|
||||||
|
|
||||||
// Inspired from https://github.com/MrCrayfish/Controllable/blob/1.14.X/src/main/java/com/mrcrayfish/controllable/client/ControllerInput.java#L686.
|
// Inspired from https://github.com/MrCrayfish/Controllable/blob/1.14.X/src/main/java/com/mrcrayfish/controllable/client/ControllerInput.java#L686.
|
||||||
private void move_mouse_to_closest_slot(@NotNull MinecraftClient client, @Nullable Screen screen)
|
private void move_mouse_to_closest_slot(@NotNull MinecraftClient client, @Nullable Screen screen)
|
||||||
{
|
{
|
||||||
@@ -469,15 +505,18 @@ public class ControllerInput
|
|||||||
this.target_mouse_x += delta_x * 0.75;
|
this.target_mouse_x += delta_x * 0.75;
|
||||||
this.target_mouse_y += delta_y * 0.75;
|
this.target_mouse_y += delta_y * 0.75;
|
||||||
} else {
|
} else {
|
||||||
mouse_speed_x = 0.F;
|
this.mouse_speed_x *= 0.3F;
|
||||||
mouse_speed_y = 0.F;
|
this.mouse_speed_y *= 0.3F;
|
||||||
}
|
}
|
||||||
this.mouse_speed_x *= .75F;
|
this.mouse_speed_x *= .75F;
|
||||||
this.mouse_speed_y *= .75F;
|
this.mouse_speed_y *= .75F;
|
||||||
|
} else {
|
||||||
|
this.mouse_speed_x *= .1F;
|
||||||
|
this.mouse_speed_y *= .1F;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.mouse_speed_x *= .1F;
|
this.mouse_speed_x *= .3F;
|
||||||
this.mouse_speed_y *= .1F;
|
this.mouse_speed_y *= .3F;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.mouse_speed_x = 0.F;
|
this.mouse_speed_x = 0.F;
|
||||||
|
|||||||
@@ -9,63 +9,26 @@
|
|||||||
|
|
||||||
package me.lambdaurora.lambdacontrols;
|
package me.lambdaurora.lambdacontrols;
|
||||||
|
|
||||||
import me.lambdaurora.lambdacontrols.mixin.AbstractContainerScreenAccessor;
|
|
||||||
import me.lambdaurora.lambdacontrols.util.CreativeInventoryScreenAccessor;
|
|
||||||
import me.lambdaurora.lambdacontrols.util.LambdaKeyBinding;
|
|
||||||
import net.fabricmc.api.ClientModInitializer;
|
import net.fabricmc.api.ClientModInitializer;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
import net.minecraft.client.gui.Element;
|
import net.minecraft.client.toast.SystemToast;
|
||||||
import net.minecraft.client.gui.screen.Screen;
|
import net.minecraft.text.LiteralText;
|
||||||
import net.minecraft.client.gui.screen.ingame.AbstractContainerScreen;
|
import net.minecraft.text.TranslatableText;
|
||||||
import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen;
|
|
||||||
import net.minecraft.client.gui.screen.ingame.InventoryScreen;
|
|
||||||
import net.minecraft.client.gui.screen.world.WorldListWidget;
|
|
||||||
import net.minecraft.client.gui.widget.AbstractPressableButtonWidget;
|
|
||||||
import net.minecraft.client.gui.widget.EntryListWidget;
|
|
||||||
import net.minecraft.client.gui.widget.SliderWidget;
|
|
||||||
import net.minecraft.client.options.GameOptions;
|
|
||||||
import net.minecraft.container.Slot;
|
|
||||||
import net.minecraft.item.ItemGroup;
|
|
||||||
import net.minecraft.util.math.MathHelper;
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.aperlambda.lambdacommon.utils.Pair;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
import org.lwjgl.glfw.GLFW;
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.nio.FloatBuffer;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
import static org.lwjgl.glfw.GLFW.GLFW_JOYSTICK_1;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the LambdaControls mod.
|
* Represents the LambdaControls mod.
|
||||||
*/
|
*/
|
||||||
public class LambdaControls implements ClientModInitializer
|
public class LambdaControls implements ClientModInitializer
|
||||||
{
|
{
|
||||||
private static LambdaControls INSTANCE;
|
private static LambdaControls INSTANCE;
|
||||||
public final Logger logger = LogManager.getLogger("LambdaControls");
|
public final Logger logger = LogManager.getLogger("LambdaControls");
|
||||||
public final LambdaControlsConfig config = new LambdaControlsConfig(this);
|
public final LambdaControlsConfig config = new LambdaControlsConfig(this);
|
||||||
public final ControllerInput controller_input = new ControllerInput(this);
|
public final ControllerInput controller_input = new ControllerInput(this);
|
||||||
private final Map<Integer, Integer> BUTTON_STATES = new HashMap<>();
|
|
||||||
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 boolean last_a_state = false;
|
|
||||||
private int cid = GLFW_JOYSTICK_1;
|
|
||||||
private boolean allow_controller_mouse = true;
|
|
||||||
private int action_gui_cooldown = 0;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onInitializeClient()
|
public void onInitializeClient()
|
||||||
@@ -80,11 +43,16 @@ public class LambdaControls implements ClientModInitializer
|
|||||||
*/
|
*/
|
||||||
public void on_mc_init(@NotNull MinecraftClient client)
|
public void on_mc_init(@NotNull MinecraftClient client)
|
||||||
{
|
{
|
||||||
|
Controller.update_mappings();
|
||||||
this.config.init_keybindings(client.options);
|
this.config.init_keybindings(client.options);
|
||||||
GLFW.glfwSetJoystickCallback((jid, event) -> {
|
GLFW.glfwSetJoystickCallback((jid, event) -> {
|
||||||
if (event == GLFW.GLFW_CONNECTED) {
|
if (event == GLFW.GLFW_CONNECTED) {
|
||||||
this.log("CONNECTED " + jid);
|
Controller controller = Controller.by_id(jid);
|
||||||
cid = jid;
|
client.getToastManager().add(new SystemToast(SystemToast.Type.TUTORIAL_HINT, new TranslatableText("lambdacontrols.controller.connected", jid),
|
||||||
|
new LiteralText(controller.get_name())));
|
||||||
|
} else if (event == GLFW.GLFW_DISCONNECTED) {
|
||||||
|
client.getToastManager().add(new SystemToast(SystemToast.Type.TUTORIAL_HINT, new TranslatableText("lambdacontrols.controller.disconnected", jid),
|
||||||
|
null));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -98,16 +66,6 @@ public class LambdaControls implements ClientModInitializer
|
|||||||
{
|
{
|
||||||
if (this.config.get_controls_mode() == ControlsMode.CONTROLLER)
|
if (this.config.get_controls_mode() == ControlsMode.CONTROLLER)
|
||||||
this.controller_input.on_tick(client);
|
this.controller_input.on_tick(client);
|
||||||
/* Decreases the cooldown for the screen focus change.
|
|
||||||
if (this.action_gui_cooldown > 0)
|
|
||||||
--this.action_gui_cooldown;
|
|
||||||
if (this.action_gui_cooldown == 0)
|
|
||||||
this.allow_controller_mouse = true;
|
|
||||||
|
|
||||||
this.prev_target_mouse_x = this.target_mouse_x;
|
|
||||||
this.prev_target_mouse_y = this.target_mouse_y;
|
|
||||||
if (LambdaControls.get().config.get_controls_mode() == ControlsMode.CONTROLLER)
|
|
||||||
this.on_controller_tick(client);*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void on_render(MinecraftClient client)
|
public void on_render(MinecraftClient client)
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import com.electronwill.nightconfig.core.file.FileConfig;
|
|||||||
import net.minecraft.client.options.GameOptions;
|
import net.minecraft.client.options.GameOptions;
|
||||||
import net.minecraft.client.options.KeyBinding;
|
import net.minecraft.client.options.KeyBinding;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -31,13 +32,21 @@ public class LambdaControlsConfig
|
|||||||
// Controller settings
|
// Controller settings
|
||||||
private double dead_zone;
|
private double dead_zone;
|
||||||
private double rotation_speed;
|
private double rotation_speed;
|
||||||
|
private double mouse_speed;
|
||||||
// Controller controls
|
// Controller controls
|
||||||
|
private String b_button;
|
||||||
private String back_button;
|
private String back_button;
|
||||||
|
private String dpad_up;
|
||||||
|
private String dpad_right;
|
||||||
|
private String dpad_down;
|
||||||
|
private String dpad_left;
|
||||||
private String forward_button;
|
private String forward_button;
|
||||||
|
private String inventory_button;
|
||||||
private String jump_button;
|
private String jump_button;
|
||||||
private String left_button;
|
private String left_button;
|
||||||
private String right_button;
|
private String right_button;
|
||||||
private String sneak_button;
|
private String sneak_button;
|
||||||
|
private String x_button;
|
||||||
|
|
||||||
public LambdaControlsConfig(@NotNull LambdaControls mod)
|
public LambdaControlsConfig(@NotNull LambdaControls mod)
|
||||||
{
|
{
|
||||||
@@ -52,15 +61,23 @@ public class LambdaControlsConfig
|
|||||||
this.controls_mode = ControlsMode.by_id(this.config.getOrElse("controls", "default")).orElse(ControlsMode.DEFAULT);
|
this.controls_mode = ControlsMode.by_id(this.config.getOrElse("controls", "default")).orElse(ControlsMode.DEFAULT);
|
||||||
this.hud_side = HudSide.by_id(this.config.getOrElse("hud.side", "left")).orElse(HudSide.LEFT);
|
this.hud_side = HudSide.by_id(this.config.getOrElse("hud.side", "left")).orElse(HudSide.LEFT);
|
||||||
// Controller settings
|
// Controller settings
|
||||||
this.dead_zone = this.config.getOrElse("controller.dead_zone", 0.25D);
|
this.dead_zone = this.config.getOrElse("controller.dead_zone", 0.25);
|
||||||
this.rotation_speed = this.config.getOrElse("controller.rotation_speed", 25.D);
|
this.rotation_speed = this.config.getOrElse("controller.rotation_speed", 40.0);
|
||||||
|
this.mouse_speed = this.config.getOrElse("controller.mouse_speed", 25.0);
|
||||||
// Controller controls
|
// Controller controls
|
||||||
|
this.b_button = this.config.getOrElse("controller.controls.b", "none").toLowerCase();
|
||||||
this.back_button = this.config.getOrElse("controller.controls.back", "none").toLowerCase();
|
this.back_button = this.config.getOrElse("controller.controls.back", "none").toLowerCase();
|
||||||
|
this.dpad_up = this.config.getOrElse("controller.controls.dpad_up", "none").toLowerCase();
|
||||||
|
this.dpad_right = this.config.getOrElse("controller.controls.dpad_right", "none").toLowerCase();
|
||||||
|
this.dpad_down = this.config.getOrElse("controller.controls.dpad_down", "none").toLowerCase();
|
||||||
|
this.dpad_left = this.config.getOrElse("controller.controls.dpad_left", "none").toLowerCase();
|
||||||
this.forward_button = this.config.getOrElse("controller.controls.forward", "none").toLowerCase();
|
this.forward_button = this.config.getOrElse("controller.controls.forward", "none").toLowerCase();
|
||||||
|
this.inventory_button = this.config.getOrElse("controller.controls.inventory", "none").toLowerCase();
|
||||||
this.jump_button = this.config.getOrElse("controller.controls.jump", "none").toLowerCase();
|
this.jump_button = this.config.getOrElse("controller.controls.jump", "none").toLowerCase();
|
||||||
this.left_button = this.config.getOrElse("controller.controls.left", "none").toLowerCase();
|
this.left_button = this.config.getOrElse("controller.controls.left", "none").toLowerCase();
|
||||||
this.right_button = this.config.getOrElse("controller.controls.right", "none").toLowerCase();
|
this.right_button = this.config.getOrElse("controller.controls.right", "none").toLowerCase();
|
||||||
this.sneak_button = this.config.getOrElse("controller.controls.sneak", "none").toLowerCase();
|
this.sneak_button = this.config.getOrElse("controller.controls.sneak", "none").toLowerCase();
|
||||||
|
this.x_button = this.config.getOrElse("controller.controls.x", "none").toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void init_keybindings(GameOptions options)
|
public void init_keybindings(GameOptions options)
|
||||||
@@ -70,14 +87,12 @@ public class LambdaControlsConfig
|
|||||||
this.keybinding_mappings.put(str, options.keyAttack);
|
this.keybinding_mappings.put(str, options.keyAttack);
|
||||||
if (!this.back_button.equals("none"))
|
if (!this.back_button.equals("none"))
|
||||||
this.keybinding_mappings.put(this.back_button, options.keyBack);
|
this.keybinding_mappings.put(this.back_button, options.keyBack);
|
||||||
str = this.config.getOrElse("controller.controls.drop", "none").toLowerCase();
|
if (!this.b_button.equals("none"))
|
||||||
if (!str.equals("none"))
|
this.keybinding_mappings.put(this.b_button, options.keyDrop);
|
||||||
this.keybinding_mappings.put(str, options.keyDrop);
|
|
||||||
if (!this.forward_button.equals("none"))
|
if (!this.forward_button.equals("none"))
|
||||||
this.keybinding_mappings.put(this.forward_button, options.keyForward);
|
this.keybinding_mappings.put(this.forward_button, options.keyForward);
|
||||||
str = this.config.getOrElse("controller.controls.inventory", "none").toLowerCase();
|
if (!this.inventory_button.equals("none"))
|
||||||
if (!str.equals("none"))
|
this.keybinding_mappings.put(this.inventory_button, options.keyInventory);
|
||||||
this.keybinding_mappings.put(str, options.keyInventory);
|
|
||||||
if (!this.jump_button.equals("none"))
|
if (!this.jump_button.equals("none"))
|
||||||
this.keybinding_mappings.put(this.jump_button, options.keyJump);
|
this.keybinding_mappings.put(this.jump_button, options.keyJump);
|
||||||
if (!this.left_button.equals("none"))
|
if (!this.left_button.equals("none"))
|
||||||
@@ -92,12 +107,15 @@ public class LambdaControlsConfig
|
|||||||
str = this.config.getOrElse("controller.controls.use", "none").toLowerCase();
|
str = this.config.getOrElse("controller.controls.use", "none").toLowerCase();
|
||||||
if (!str.equals("none"))
|
if (!str.equals("none"))
|
||||||
this.keybinding_mappings.put(str, options.keyUse);
|
this.keybinding_mappings.put(str, options.keyUse);
|
||||||
|
if (!this.x_button.equals("none"))
|
||||||
|
this.keybinding_mappings.put(this.x_button, options.keySwapHands);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void save()
|
public void save()
|
||||||
{
|
{
|
||||||
this.config.set("controller.dead_zone", this.dead_zone);
|
this.config.set("controller.dead_zone", this.dead_zone);
|
||||||
this.config.set("controller.rotation_speed", this.rotation_speed);
|
this.config.set("controller.rotation_speed", this.rotation_speed);
|
||||||
|
this.config.set("controller.mouse_speed", this.mouse_speed);
|
||||||
this.config.save();
|
this.config.save();
|
||||||
this.mod.log("Configuration saved.");
|
this.mod.log("Configuration saved.");
|
||||||
}
|
}
|
||||||
@@ -144,6 +162,33 @@ public class LambdaControlsConfig
|
|||||||
this.config.set("hud.side", hud_side.get_name());
|
this.config.set("hud.side", hud_side.get_name());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the used controller.
|
||||||
|
*
|
||||||
|
* @return The used controller.
|
||||||
|
*/
|
||||||
|
public @NotNull Controller get_controller()
|
||||||
|
{
|
||||||
|
Object raw = this.config.getRaw("controller.id");
|
||||||
|
if (raw instanceof Number) {
|
||||||
|
return Controller.by_id((Integer) raw);
|
||||||
|
} else if (raw instanceof String) {
|
||||||
|
return Controller.by_guid((String) raw).orElse(Controller.by_id(GLFW.GLFW_JOYSTICK_1));
|
||||||
|
}
|
||||||
|
return Controller.by_id(GLFW.GLFW_JOYSTICK_1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the used controller.
|
||||||
|
*
|
||||||
|
* @param controller The used controller.
|
||||||
|
*/
|
||||||
|
public void set_controller(@NotNull Controller controller)
|
||||||
|
{
|
||||||
|
String guid = controller.get_guid();
|
||||||
|
this.config.set("controller.id", guid.equals("") ? controller.get_id() : guid);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the controller's dead zone from the configuration.
|
* Gets the controller's dead zone from the configuration.
|
||||||
*
|
*
|
||||||
@@ -184,6 +229,26 @@ public class LambdaControlsConfig
|
|||||||
this.rotation_speed = rotation_speed;
|
this.rotation_speed = rotation_speed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the controller's mouse speed.
|
||||||
|
*
|
||||||
|
* @return The mouse speed.
|
||||||
|
*/
|
||||||
|
public double get_mouse_speed()
|
||||||
|
{
|
||||||
|
return this.mouse_speed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the controller's mouse speed.
|
||||||
|
*
|
||||||
|
* @param mouse_speed The mouse speed.
|
||||||
|
*/
|
||||||
|
public void set_mouse_speed(double mouse_speed)
|
||||||
|
{
|
||||||
|
this.mouse_speed = mouse_speed;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the keybindings.
|
* Returns the keybindings.
|
||||||
*
|
*
|
||||||
@@ -199,11 +264,41 @@ public class LambdaControlsConfig
|
|||||||
return Optional.ofNullable(this.keybinding_mappings.get(id));
|
return Optional.ofNullable(this.keybinding_mappings.get(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the B button mapping.
|
||||||
|
*
|
||||||
|
* @return The B button mapping.
|
||||||
|
*/
|
||||||
|
public String get_b_button()
|
||||||
|
{
|
||||||
|
return this.b_button;
|
||||||
|
}
|
||||||
|
|
||||||
public String get_back_button()
|
public String get_back_button()
|
||||||
{
|
{
|
||||||
return this.back_button;
|
return this.back_button;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String get_dpad_up()
|
||||||
|
{
|
||||||
|
return this.dpad_up;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String get_dpad_right()
|
||||||
|
{
|
||||||
|
return this.dpad_right;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String get_dpad_down()
|
||||||
|
{
|
||||||
|
return this.dpad_down;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String get_dpad_left()
|
||||||
|
{
|
||||||
|
return this.dpad_left;
|
||||||
|
}
|
||||||
|
|
||||||
public String get_forward_button()
|
public String get_forward_button()
|
||||||
{
|
{
|
||||||
return this.forward_button;
|
return this.forward_button;
|
||||||
@@ -219,6 +314,16 @@ public class LambdaControlsConfig
|
|||||||
return this.config.getOrElse("controller.controls.hotbar_right", "none").toLowerCase();
|
return this.config.getOrElse("controller.controls.hotbar_right", "none").toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the Inventory button mapping.
|
||||||
|
*
|
||||||
|
* @return The Inventory button mapping.
|
||||||
|
*/
|
||||||
|
public String get_inventory_button()
|
||||||
|
{
|
||||||
|
return this.inventory_button;
|
||||||
|
}
|
||||||
|
|
||||||
public String get_jump_button()
|
public String get_jump_button()
|
||||||
{
|
{
|
||||||
return this.jump_button;
|
return this.jump_button;
|
||||||
@@ -244,6 +349,50 @@ public class LambdaControlsConfig
|
|||||||
return this.config.getOrElse("controller.controls.start", "none").toLowerCase();
|
return this.config.getOrElse("controller.controls.start", "none").toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String get_x_button()
|
||||||
|
{
|
||||||
|
return this.x_button;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean is_b_button(int button)
|
||||||
|
{
|
||||||
|
return this.get_b_button().equals("button_" + button);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean is_back_button(int btn, boolean is_btn, int state)
|
||||||
|
{
|
||||||
|
if (!is_btn && state == 0)
|
||||||
|
return false;
|
||||||
|
return this.get_back_button().equals((is_btn ? "button_" : "axe_") + btn + (is_btn ? "" : (state == 1 ? "+" : "-")));
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean is_dpad_up(int button)
|
||||||
|
{
|
||||||
|
return this.get_dpad_up().equals("button_" + button);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean is_dpad_right(int button)
|
||||||
|
{
|
||||||
|
return this.get_dpad_right().equals("button_" + button);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean is_dpad_down(int button)
|
||||||
|
{
|
||||||
|
return this.get_dpad_down().equals("button_" + button);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean is_dpad_left(int button)
|
||||||
|
{
|
||||||
|
return this.get_dpad_left().equals("button_" + button);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean is_forward_button(int btn, boolean is_btn, int state)
|
||||||
|
{
|
||||||
|
if (!is_btn && state == 0)
|
||||||
|
return false;
|
||||||
|
return this.get_forward_button().equals((is_btn ? "button_" : "axe_") + btn + (is_btn ? "" : (state == 1 ? "+" : "-")));
|
||||||
|
}
|
||||||
|
|
||||||
public boolean is_hotbar_left_button(int button)
|
public boolean is_hotbar_left_button(int button)
|
||||||
{
|
{
|
||||||
return this.get_hotbar_left_button().equals("button_" + button);
|
return this.get_hotbar_left_button().equals("button_" + button);
|
||||||
@@ -254,18 +403,9 @@ public class LambdaControlsConfig
|
|||||||
return this.get_hotbar_right_button().equals("button_" + button);
|
return this.get_hotbar_right_button().equals("button_" + button);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean is_back_button(int btn, boolean is_btn, int state)
|
public boolean is_inventory_button(int btn)
|
||||||
{
|
{
|
||||||
if (!is_btn && state == 0)
|
return this.get_inventory_button().equals("button_" + btn);
|
||||||
return false;
|
|
||||||
return this.get_back_button().equals((is_btn ? "button_" : "axe_") + btn + (is_btn ? "" : (state == 1 ? "+" : "-")));
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean is_forward_button(int btn, boolean is_btn, int state)
|
|
||||||
{
|
|
||||||
if (!is_btn && state == 0)
|
|
||||||
return false;
|
|
||||||
return this.get_forward_button().equals((is_btn ? "button_" : "axe_") + btn + (is_btn ? "" : (state == 1 ? "+" : "-")));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean is_jump_button(int btn)
|
public boolean is_jump_button(int btn)
|
||||||
@@ -297,6 +437,11 @@ public class LambdaControlsConfig
|
|||||||
return this.get_start_button().equals("button_" + btn);
|
return this.get_start_button().equals("button_" + btn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean is_x_button(int btn)
|
||||||
|
{
|
||||||
|
return this.get_x_button().equals("button_" + btn);
|
||||||
|
}
|
||||||
|
|
||||||
public String get_view_down_control()
|
public String get_view_down_control()
|
||||||
{
|
{
|
||||||
return this.config.getOrElse("controller.controls.view_down", "none").toLowerCase();
|
return this.config.getOrElse("controller.controls.view_down", "none").toLowerCase();
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ public class LambdaControlsSettingsScreen extends Screen
|
|||||||
private final GameOptions options;
|
private final GameOptions options;
|
||||||
private final Option dead_zone_option;
|
private final Option dead_zone_option;
|
||||||
private final Option rotation_speed_option;
|
private final Option rotation_speed_option;
|
||||||
|
private final Option mouse_speed_option;
|
||||||
|
|
||||||
public LambdaControlsSettingsScreen(Screen parent, @NotNull GameOptions options)
|
public LambdaControlsSettingsScreen(Screen parent, @NotNull GameOptions options)
|
||||||
{
|
{
|
||||||
@@ -39,18 +40,34 @@ public class LambdaControlsSettingsScreen extends Screen
|
|||||||
this.mod = LambdaControls.get();
|
this.mod = LambdaControls.get();
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
this.options = options;
|
this.options = options;
|
||||||
this.dead_zone_option = new DoubleOption("lambdacontrols.menu.dead_zone", 0.05D, 1.0D, 0.05F, game_options -> this.mod.config.get_dead_zone(),
|
this.dead_zone_option = new DoubleOption("lambdacontrols.menu.dead_zone", 0.05, 1.0, 0.05F, game_options -> this.mod.config.get_dead_zone(),
|
||||||
(game_options, new_value) -> {
|
(game_options, new_value) -> {
|
||||||
synchronized (this.mod.config) {
|
synchronized (this.mod.config) {
|
||||||
this.mod.config.set_dead_zone(new_value);
|
this.mod.config.set_dead_zone(new_value);
|
||||||
}
|
}
|
||||||
}, (game_options, option) -> option.getDisplayPrefix() + option.get(options));
|
}, (game_options, option) -> {
|
||||||
this.rotation_speed_option = new DoubleOption("lambdacontrols.menu.rotation_speed", 0.0D, 50.0D, 0.5F, game_options -> this.mod.config.get_rotation_speed(),
|
String value = String.valueOf(option.get(options));
|
||||||
|
return option.getDisplayPrefix() + value.substring(0, value.length() > 5 ? 5 : value.length());
|
||||||
|
});
|
||||||
|
this.rotation_speed_option = new DoubleOption("lambdacontrols.menu.rotation_speed", 0.0, 50.0, 0.5F, game_options -> this.mod.config.get_rotation_speed(),
|
||||||
(game_options, new_value) -> {
|
(game_options, new_value) -> {
|
||||||
synchronized (this.mod.config) {
|
synchronized (this.mod.config) {
|
||||||
this.mod.config.set_rotation_speed(new_value);
|
this.mod.config.set_rotation_speed(new_value);
|
||||||
}
|
}
|
||||||
}, (game_options, option) -> option.getDisplayPrefix() + option.get(options));
|
}, (game_options, option) -> option.getDisplayPrefix() + option.get(options));
|
||||||
|
this.mouse_speed_option = new DoubleOption("lambdacontrols.menu.mouse_speed", 0.0, 50.0, 0.5F, game_options -> this.mod.config.get_mouse_speed(),
|
||||||
|
(game_options, new_value) -> {
|
||||||
|
synchronized (this.mod.config) {
|
||||||
|
this.mod.config.set_mouse_speed(new_value);
|
||||||
|
}
|
||||||
|
}, (game_options, option) -> option.getDisplayPrefix() + option.get(options));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removed()
|
||||||
|
{
|
||||||
|
this.mod.config.save();
|
||||||
|
super.removed();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -86,6 +103,7 @@ public class LambdaControlsSettingsScreen extends Screen
|
|||||||
btn -> this.minecraft.openScreen(new ControlsOptionsScreen(this, this.options))));
|
btn -> this.minecraft.openScreen(new ControlsOptionsScreen(this, this.options))));
|
||||||
this.addButton(this.dead_zone_option.createButton(this.options, this.width / 2 - 155, (y += spacing + button_height), 150));
|
this.addButton(this.dead_zone_option.createButton(this.options, this.width / 2 - 155, (y += spacing + button_height), 150));
|
||||||
this.addButton(this.rotation_speed_option.createButton(this.options, this.width / 2 - 155 + 160, y, 150));
|
this.addButton(this.rotation_speed_option.createButton(this.options, this.width / 2 - 155 + 160, y, 150));
|
||||||
|
this.addButton(this.mouse_speed_option.createButton(this.options, this.width / 2 - 155, (y += spacing + button_height), 150));
|
||||||
this.addButton(new ButtonWidget(this.width / 2 - 155 + 160, this.height - 29, 150, button_height, I18n.translate("gui.done"), (buttonWidget) -> {
|
this.addButton(new ButtonWidget(this.width / 2 - 155 + 160, this.height - 29, 150, button_height, I18n.translate("gui.done"), (buttonWidget) -> {
|
||||||
this.minecraft.openScreen(this.parent);
|
this.minecraft.openScreen(this.parent);
|
||||||
}));
|
}));
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright © 2019 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.mixin;
|
|
||||||
|
|
||||||
import net.minecraft.client.gui.screen.ingame.AbstractContainerScreen;
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
|
||||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
|
||||||
|
|
||||||
@Mixin(AbstractContainerScreen.class)
|
|
||||||
public interface AbstractContainerScreenAccessor
|
|
||||||
{
|
|
||||||
@Accessor("left")
|
|
||||||
int get_left();
|
|
||||||
|
|
||||||
@Accessor("top")
|
|
||||||
int get_top();
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2019 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.mixin;
|
||||||
|
|
||||||
|
import me.lambdaurora.lambdacontrols.util.AbstractContainerScreenAccessor;
|
||||||
|
import net.minecraft.client.gui.screen.ingame.AbstractContainerScreen;
|
||||||
|
import net.minecraft.container.Slot;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the mixin for the class AbstractContainerScreen.
|
||||||
|
*/
|
||||||
|
@Mixin(AbstractContainerScreen.class)
|
||||||
|
public abstract class AbstractContainerScreenMixin implements AbstractContainerScreenAccessor
|
||||||
|
{
|
||||||
|
@Shadow
|
||||||
|
protected int left;
|
||||||
|
|
||||||
|
@Shadow
|
||||||
|
protected int top;
|
||||||
|
|
||||||
|
@Shadow
|
||||||
|
protected abstract Slot getSlotAt(double xPosition, double yPosition);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int get_left()
|
||||||
|
{
|
||||||
|
return this.left;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int get_top()
|
||||||
|
{
|
||||||
|
return this.top;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Slot get_slot_at(double pos_x, double pos_y)
|
||||||
|
{
|
||||||
|
return this.getSlotAt(pos_x, pos_y);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -27,7 +27,7 @@ public class GameRendererMixin
|
|||||||
@Final
|
@Final
|
||||||
private MinecraftClient client;
|
private MinecraftClient client;
|
||||||
|
|
||||||
@Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/Screen;render(IIF)V"))
|
@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 on_render(float tick_delta, long start_time, boolean full_render, CallbackInfo ci)
|
||||||
{
|
{
|
||||||
if (this.client.currentScreen != null && LambdaControls.get().config.get_controls_mode() == ControlsMode.CONTROLLER)
|
if (this.client.currentScreen != null && LambdaControls.get().config.get_controls_mode() == ControlsMode.CONTROLLER)
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2019 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.util;
|
||||||
|
|
||||||
|
import net.minecraft.container.Slot;
|
||||||
|
import net.minecraft.item.ItemGroup;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents an accessor to AbstractContainerScreen.
|
||||||
|
*/
|
||||||
|
public interface AbstractContainerScreenAccessor
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Gets the left coordinate of the GUI.
|
||||||
|
*
|
||||||
|
* @return The left coordinate of the GUI.
|
||||||
|
*/
|
||||||
|
int get_left();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the top coordinate of the GUI.
|
||||||
|
*
|
||||||
|
* @return The top coordinate of the GUI.
|
||||||
|
*/
|
||||||
|
int get_top();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the slot at position.
|
||||||
|
*
|
||||||
|
* @param pos_x The X position to check.
|
||||||
|
* @param pos_y The Y position to check.
|
||||||
|
* @return The slot at the specified position.
|
||||||
|
*/
|
||||||
|
Slot get_slot_at(double pos_x, double pos_y);
|
||||||
|
}
|
||||||
@@ -4,6 +4,9 @@
|
|||||||
"lambdacontrols.menu.dead_zone": "Dead zone",
|
"lambdacontrols.menu.dead_zone": "Dead zone",
|
||||||
"lambdacontrols.menu.hud_side": "HUD side",
|
"lambdacontrols.menu.hud_side": "HUD side",
|
||||||
"lambdacontrols.menu.rotation_speed": "Rotation speed",
|
"lambdacontrols.menu.rotation_speed": "Rotation speed",
|
||||||
|
"lambdacontrols.menu.mouse_speed": "Mouse speed",
|
||||||
|
"lambdacontrols.controller.connected": "Controller %d connected.",
|
||||||
|
"lambdacontrols.controller.disconnected": "Controller %d disconnected.",
|
||||||
"lambdacontrols.controls_mode.default": "Keyboard/Mouse",
|
"lambdacontrols.controls_mode.default": "Keyboard/Mouse",
|
||||||
"lambdacontrols.controls_mode.controller": "Controller",
|
"lambdacontrols.controls_mode.controller": "Controller",
|
||||||
"lambdacontrols.controls_mode.touchscreen": "Touchscreen",
|
"lambdacontrols.controls_mode.touchscreen": "Touchscreen",
|
||||||
|
|||||||
@@ -9,13 +9,23 @@ controls = "default"
|
|||||||
|
|
||||||
# Controller settings
|
# Controller settings
|
||||||
[controller]
|
[controller]
|
||||||
dead_zone = 0.25
|
# Controller to use.
|
||||||
rotation_speed = 25.0
|
id = 0
|
||||||
|
# Controller's dead zone.
|
||||||
|
dead_zone = 0.20
|
||||||
|
# Rotation speed for look directions.
|
||||||
|
rotation_speed = 40.0
|
||||||
|
# Mouse speed in GUI.
|
||||||
|
mouse_speed = 30.0
|
||||||
# Controller controls
|
# Controller controls
|
||||||
[controller.controls]
|
[controller.controls]
|
||||||
attack = "button_7"
|
attack = "button_7"
|
||||||
|
b = "button_1"
|
||||||
back = "axe_1+"
|
back = "axe_1+"
|
||||||
drop = "button_2"
|
dpad_up = "button_13"
|
||||||
|
dpad_right = "button_14"
|
||||||
|
dpad_down = "button_15"
|
||||||
|
dpad_left = "button_16"
|
||||||
forward = "axe_1-"
|
forward = "axe_1-"
|
||||||
hotbar_left = "button_4"
|
hotbar_left = "button_4"
|
||||||
hotbar_right = "button_5"
|
hotbar_right = "button_5"
|
||||||
@@ -31,6 +41,7 @@ controls = "default"
|
|||||||
view_left = "axe_2-"
|
view_left = "axe_2-"
|
||||||
view_right = "axe_2+"
|
view_right = "axe_2+"
|
||||||
view_up = "axe_3-"
|
view_up = "axe_3-"
|
||||||
|
x = "button_2"
|
||||||
|
|
||||||
# Colors
|
# Colors
|
||||||
[colors]
|
[colors]
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"compatibilityLevel": "JAVA_8",
|
"compatibilityLevel": "JAVA_8",
|
||||||
"client": [
|
"client": [
|
||||||
"AbstractButtonWidgetAccessor",
|
"AbstractButtonWidgetAccessor",
|
||||||
"AbstractContainerScreenAccessor",
|
"AbstractContainerScreenMixin",
|
||||||
"CreativeInventoryScreenMixin",
|
"CreativeInventoryScreenMixin",
|
||||||
"GameRendererMixin",
|
"GameRendererMixin",
|
||||||
"InGameHudMixin",
|
"InGameHudMixin",
|
||||||
|
|||||||
Reference in New Issue
Block a user