mirror of
https://github.com/TeamMidnightDust/MidnightControls.git
synced 2025-12-14 15:45:09 +01:00
✨ Add controller settings GUI and more WIP on controller support.
This commit is contained in:
487
src/main/java/me/lambdaurora/lambdacontrols/ControllerInput.java
Normal file
487
src/main/java/me/lambdaurora/lambdacontrols/ControllerInput.java
Normal file
@@ -0,0 +1,487 @@
|
||||
/*
|
||||
* 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 me.lambdaurora.lambdacontrols.mixin.AbstractContainerScreenAccessor;
|
||||
import me.lambdaurora.lambdacontrols.util.CreativeInventoryScreenAccessor;
|
||||
import me.lambdaurora.lambdacontrols.util.LambdaKeyBinding;
|
||||
import me.lambdaurora.lambdacontrols.util.MouseAccessor;
|
||||
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.ingame.AbstractContainerScreen;
|
||||
import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen;
|
||||
import net.minecraft.client.gui.screen.world.WorldListWidget;
|
||||
import net.minecraft.client.gui.widget.*;
|
||||
import net.minecraft.client.options.KeyBinding;
|
||||
import net.minecraft.container.Slot;
|
||||
import net.minecraft.item.ItemGroup;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import org.aperlambda.lambdacommon.utils.Pair;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
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;
|
||||
|
||||
public class ControllerInput
|
||||
{
|
||||
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, Float> AXE_STATES = new HashMap<>();
|
||||
private final LambdaControls mod;
|
||||
private final LambdaControlsConfig config;
|
||||
private int controller = GLFW.GLFW_JOYSTICK_3;
|
||||
private int action_gui_cooldown = 0;
|
||||
private boolean last_a_state = false;
|
||||
private boolean continuous_sneak = false;
|
||||
private int last_sneak = 0;
|
||||
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;
|
||||
|
||||
public ControllerInput(@NotNull LambdaControls mod)
|
||||
{
|
||||
this.mod = mod;
|
||||
this.config = mod.config;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called every Minecraft tick.
|
||||
*
|
||||
* @param client The client instance.
|
||||
*/
|
||||
public void on_tick(@NotNull MinecraftClient client)
|
||||
{
|
||||
BUTTON_COOLDOWNS.entrySet().stream().filter(entry -> entry.getValue() > 0).forEach(entry -> BUTTON_COOLDOWNS.put(entry.getKey(), entry.getValue() - 1));
|
||||
// Decreases the last_sneak counter which allows to double press to sneak continuously.
|
||||
if (this.last_sneak > 0)
|
||||
--this.last_sneak;
|
||||
// Decreases the cooldown for GUI actions.
|
||||
if (this.action_gui_cooldown > 0)
|
||||
--this.action_gui_cooldown;
|
||||
this.prev_target_yaw = this.target_yaw;
|
||||
this.prev_target_pitch = this.target_pitch;
|
||||
this.fetch_button_input(client);
|
||||
this.fetch_axe_input(client);
|
||||
}
|
||||
|
||||
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) {
|
||||
double mouse_x = prev_target_mouse_x + (this.target_mouse_x - this.prev_target_mouse_x) * client.getTickDelta() + 0.5;
|
||||
double mouse_y = 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);
|
||||
}
|
||||
}
|
||||
|
||||
public void on_render(@NotNull MinecraftClient client)
|
||||
{
|
||||
if (client.currentScreen == null && (this.prev_target_yaw != this.target_yaw || this.prev_target_pitch != this.target_pitch)) {
|
||||
float rotation_yaw = (float) (client.player.prevYaw + (this.target_yaw - client.player.prevYaw) * client.getTickDelta());
|
||||
float rotation_pitch = (float) (client.player.prevPitch + (this.target_pitch - client.player.prevPitch) * client.getTickDelta());
|
||||
client.player.yaw = rotation_yaw;
|
||||
client.player.pitch = MathHelper.clamp(rotation_pitch, -90.F, 90.F);
|
||||
if (client.player.isRiding()) {
|
||||
client.player.getVehicle().copyPositionAndRotation(client.player);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void on_screen_open(@NotNull MinecraftClient client, int window_width, int window_height)
|
||||
{
|
||||
if (client.currentScreen == null) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
private void fetch_button_input(@NotNull MinecraftClient client)
|
||||
{
|
||||
ByteBuffer buffer = GLFW.glfwGetJoystickButtons(this.controller);
|
||||
if (buffer != null) {
|
||||
for (int i = 0; i < buffer.limit(); i++) {
|
||||
boolean btn_state = buffer.get() == (byte) 1;
|
||||
boolean previous_state = BUTTON_STATES.getOrDefault(i, false);
|
||||
|
||||
if (btn_state != previous_state) {
|
||||
this.handle_button(client, i, btn_state ? 0 : 1, btn_state);
|
||||
if (btn_state)
|
||||
BUTTON_COOLDOWNS.put(i, 5);
|
||||
} else if (btn_state) {
|
||||
if (BUTTON_COOLDOWNS.getOrDefault(i, 0) == 0) {
|
||||
BUTTON_COOLDOWNS.put(i, 5);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void fetch_axe_input(@NotNull MinecraftClient client)
|
||||
{
|
||||
FloatBuffer buffer = GLFW.glfwGetJoystickAxes(this.controller);
|
||||
if (buffer != null) {
|
||||
for (int i = 0; i < buffer.limit(); i++) {
|
||||
float value = buffer.get();
|
||||
float abs_value = Math.abs(value);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handle_button(@NotNull MinecraftClient client, int button, int action, boolean state)
|
||||
{
|
||||
if (action == 0) {
|
||||
// Handles RB and LB buttons.
|
||||
if (this.config.is_hotbar_left_button(button) || this.config.is_hotbar_right_button(button)) {
|
||||
this.handle_rb_lb(client, this.config.is_hotbar_right_button(button));
|
||||
return;
|
||||
}
|
||||
|
||||
// Handles when the player presses the Start button.
|
||||
if (this.config.is_start_button(button)) {
|
||||
// If in game, then pause the game.
|
||||
if (client.currentScreen == null)
|
||||
client.openPauseMenu(false);
|
||||
else // Else just close the current screen.
|
||||
client.currentScreen.onClose();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.config.is_jump_button(button) && client.currentScreen != null) {
|
||||
if (this.action_gui_cooldown == 0) {
|
||||
Element focused = client.currentScreen.getFocused();
|
||||
if (focused != null)
|
||||
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.
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handles sneak button and continuous sneak.
|
||||
if (this.config.is_sneak_button(button) && client.player != null) {
|
||||
if (action == 0) {
|
||||
if (this.continuous_sneak) {
|
||||
this.set_sneaking(client, this.continuous_sneak = false);
|
||||
} else if (this.last_sneak > 3) {
|
||||
this.set_sneaking(client, this.continuous_sneak = true);
|
||||
} else {
|
||||
this.set_sneaking(client, true);
|
||||
this.last_sneak = 15;
|
||||
}
|
||||
} else if (action == 1) {
|
||||
if (this.continuous_sneak)
|
||||
return;
|
||||
this.set_sneaking(client, false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.config.is_jump_button(button) && client.currentScreen != null) {
|
||||
if (this.last_a_state != state) {
|
||||
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();
|
||||
if (state) {
|
||||
client.currentScreen.mouseClicked(mouse_x, mouse_y, GLFW.GLFW_MOUSE_BUTTON_1);
|
||||
} else {
|
||||
client.currentScreen.mouseReleased(mouse_x, mouse_y, GLFW.GLFW_MOUSE_BUTTON_1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (client.currentScreen == null && action != 2) {
|
||||
Optional<KeyBinding> key_binding = this.config.get_keybind("button_" + button);
|
||||
key_binding.ifPresent(keyBinding -> ((LambdaKeyBinding) keyBinding).handle_press_state(action != 1));
|
||||
}
|
||||
}
|
||||
|
||||
private void handle_axe(@NotNull MinecraftClient client, int axe, float value, float abs_value, int state)
|
||||
{
|
||||
int as_button_state = value > 0.5F ? 1 : (value < -0.5F ? 2 : 0);
|
||||
double dead_zone = this.config.get_dead_zone();
|
||||
if (client.currentScreen == null) {
|
||||
this.config.get_keybind("axe_" + axe + "+").ifPresent(key_binding -> ((LambdaKeyBinding) key_binding).handle_press_state(as_button_state == 1));
|
||||
this.config.get_keybind("axe_" + axe + "-").ifPresent(key_binding -> ((LambdaKeyBinding) key_binding).handle_press_state(as_button_state == 2));
|
||||
|
||||
// Handles the look direction.
|
||||
if (this.config.is_look_axis(axe) && client.player != null) {
|
||||
if (this.config.is_view_down_control(axe, state)) {
|
||||
if (this.config.get_view_down_control().endsWith("+"))
|
||||
this.target_pitch = client.player.pitch + (this.config.get_rotation_speed() * (abs_value - dead_zone) / (1.0 - dead_zone)) * 0.33D;
|
||||
else
|
||||
this.target_pitch = client.player.pitch - (this.config.get_rotation_speed() * (abs_value + dead_zone) / (1.0 - dead_zone)) * 0.33D;
|
||||
this.target_pitch = MathHelper.clamp(this.target_pitch, -90.0D, 90.0D);
|
||||
} else if (this.config.is_view_up_control(axe, state)) {
|
||||
if (this.config.get_view_up_control().endsWith("+"))
|
||||
this.target_pitch = client.player.pitch + (this.config.get_rotation_speed() * (abs_value - dead_zone) / (1.0 - dead_zone)) * 0.33D;
|
||||
else
|
||||
this.target_pitch = client.player.pitch - (this.config.get_rotation_speed() * (abs_value + dead_zone) / (1.0 - dead_zone)) * 0.33D;
|
||||
this.target_pitch = MathHelper.clamp(this.target_pitch, -90.0D, 90.0D);
|
||||
}
|
||||
if (this.config.is_view_left_control(axe, state)) {
|
||||
if (this.config.get_view_left_control().endsWith("+"))
|
||||
this.target_yaw = client.player.yaw + (this.config.get_rotation_speed() * (abs_value - dead_zone) / (1.0 - dead_zone)) * 0.33D;
|
||||
else
|
||||
this.target_yaw = client.player.yaw - (this.config.get_rotation_speed() * (abs_value + dead_zone) / (1.0 - dead_zone)) * 0.33D;
|
||||
} else if (this.config.is_view_right_control(axe, state)) {
|
||||
if (this.config.get_view_right_control().endsWith("+"))
|
||||
this.target_yaw = client.player.yaw + (this.config.get_rotation_speed() * (abs_value - dead_zone) / (1.0 - dead_zone)) * 0.33D;
|
||||
else
|
||||
this.target_yaw = client.player.yaw - (this.config.get_rotation_speed() * (abs_value + dead_zone) / (1.0 - dead_zone)) * 0.33D;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
boolean allow_mouse_control = true;
|
||||
|
||||
if (this.action_gui_cooldown == 0 && this.config.is_movement_axis(axe)) {
|
||||
if (this.config.is_forward_button(axe, false, as_button_state)) {
|
||||
allow_mouse_control = this.change_focus(client.currentScreen, false);
|
||||
} else if (this.config.is_back_button(axe, false, as_button_state)) {
|
||||
allow_mouse_control = this.change_focus(client.currentScreen, true);
|
||||
} else if (this.config.is_left_button(axe, false, as_button_state)) {
|
||||
allow_mouse_control = this.handle_left_right(client.currentScreen, false);
|
||||
} else if (this.config.is_right_button(axe, false, as_button_state)) {
|
||||
allow_mouse_control = this.handle_left_right(client.currentScreen, true);
|
||||
}
|
||||
}
|
||||
|
||||
float movement_x = 0.0F;
|
||||
float movement_y = 0.0F;
|
||||
|
||||
if (this.config.is_back_button(axe, false, (value > 0 ? 1 : 2))) {
|
||||
movement_y = abs_value;
|
||||
} else if (this.config.is_forward_button(axe, false, (value > 0 ? 1 : 2))) {
|
||||
movement_y = -abs_value;
|
||||
} else if (this.config.is_left_button(axe, false, (value > 0 ? 1 : 2))) {
|
||||
movement_x = -abs_value;
|
||||
} else if (this.config.is_right_button(axe, false, (value > 0 ? 1 : 2))) {
|
||||
movement_x = abs_value;
|
||||
}
|
||||
|
||||
if (client.currentScreen != null && allow_mouse_control) {
|
||||
boolean moving = Math.abs(movement_y) >= dead_zone || Math.abs(movement_x) >= dead_zone;
|
||||
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();
|
||||
prev_target_mouse_x = target_mouse_x = (int) mouse_x;
|
||||
prev_target_mouse_y = target_mouse_y = (int) mouse_y;
|
||||
}
|
||||
|
||||
if (Math.abs(movement_x) >= dead_zone)
|
||||
this.mouse_speed_x = movement_x;
|
||||
else
|
||||
this.mouse_speed_x = 0.F;
|
||||
|
||||
if (Math.abs(movement_y) >= dead_zone)
|
||||
this.mouse_speed_y = movement_y;
|
||||
else
|
||||
this.mouse_speed_y = 0.F;
|
||||
} else {
|
||||
this.mouse_speed_x = 0.F;
|
||||
this.mouse_speed_y = 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_rotation_speed();
|
||||
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 = MathHelper.clamp(this.target_mouse_y, 0, client.window.getHeight());
|
||||
}
|
||||
|
||||
//this.move_mouse_to_closest_slot(client, client.currentScreen);
|
||||
}
|
||||
|
||||
this.prev_x_axis = movement_x;
|
||||
this.prev_y_axis = movement_y;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the press on RB on LB.
|
||||
*
|
||||
* @param client The client's instance.
|
||||
* @param right True if RB is pressed, else false.
|
||||
*/
|
||||
private void handle_rb_lb(@NotNull MinecraftClient client, boolean right)
|
||||
{
|
||||
// When ingame
|
||||
if (client.currentScreen == null) {
|
||||
if (right)
|
||||
client.player.inventory.selectedSlot = client.player.inventory.selectedSlot == 8 ? 0 : client.player.inventory.selectedSlot + 1;
|
||||
else
|
||||
client.player.inventory.selectedSlot = client.player.inventory.selectedSlot == 0 ? 8 : client.player.inventory.selectedSlot - 1;
|
||||
} else if (client.currentScreen instanceof CreativeInventoryScreen) {
|
||||
CreativeInventoryScreenAccessor creative_inventory = (CreativeInventoryScreenAccessor) client.currentScreen;
|
||||
int current_selected_tab = creative_inventory.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.set_selected_tab(ItemGroup.GROUPS[next_tab]);
|
||||
}
|
||||
}
|
||||
|
||||
private void handle_a_button(@NotNull Element focused)
|
||||
{
|
||||
if (focused instanceof AbstractPressableButtonWidget) {
|
||||
AbstractPressableButtonWidget button_widget = (AbstractPressableButtonWidget) focused;
|
||||
button_widget.playDownSound(MinecraftClient.getInstance().getSoundManager());
|
||||
button_widget.onPress();
|
||||
} else if (focused instanceof WorldListWidget) {
|
||||
WorldListWidget list = (WorldListWidget) focused;
|
||||
list.method_20159().ifPresent(WorldListWidget.LevelItem::play);
|
||||
} else if (focused instanceof ParentElement) {
|
||||
Element child_focused = ((ParentElement) focused).getFocused();
|
||||
if (child_focused != null)
|
||||
this.handle_a_button(child_focused);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the left and right buttons.
|
||||
*
|
||||
* @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)
|
||||
{
|
||||
Element focused = screen.getFocused();
|
||||
if (focused != null)
|
||||
return this.handle_right_left_element(focused, right);
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean handle_right_left_element(@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.
|
||||
return false;
|
||||
} else if (element instanceof ParentElement) {
|
||||
ParentElement entry_list = (ParentElement) element;
|
||||
Element focused = entry_list.getFocused();
|
||||
if (focused == null)
|
||||
return true;
|
||||
return this.handle_right_left_element(focused, right);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets if the player is sneaking.
|
||||
*
|
||||
* @param client The client's instance.
|
||||
* @param sneaking True if the player is sneaking, else false.
|
||||
*/
|
||||
private void set_sneaking(@NotNull MinecraftClient client, boolean sneaking)
|
||||
{
|
||||
((LambdaKeyBinding) client.options.keySneak).handle_press_state(sneaking);
|
||||
}
|
||||
|
||||
private boolean change_focus(@NotNull Screen screen, boolean down)
|
||||
{
|
||||
if (!screen.changeFocus(down)) {
|
||||
if (screen.changeFocus(down)) {
|
||||
this.action_gui_cooldown = 5;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
this.action_gui_cooldown = 5;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
// 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.get_left();
|
||||
int gui_top = accessor.get_top();
|
||||
int mouse_x = (int) (target_mouse_x * (double) client.window.getScaledWidth() / (double) client.window.getWidth());
|
||||
int mouse_y = (int) (target_mouse_y * (double) client.window.getScaledHeight() / (double) client.window.getHeight());
|
||||
|
||||
// Finds the closest slot in the GUI within 14 pixels.
|
||||
Optional<Pair<Slot, Double>> closest_slot = inventory_screen.getContainer().slotList.parallelStream()
|
||||
.map(slot -> {
|
||||
int pos_x = gui_left + slot.xPosition + 8;
|
||||
int pos_y = gui_top + 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));
|
||||
return Pair.of(slot, distance);
|
||||
}).filter(entry -> entry.get_value() <= 14.0)
|
||||
.min(Comparator.comparingDouble(Pair::get_value));
|
||||
|
||||
if (closest_slot.isPresent()) {
|
||||
Slot slot = closest_slot.get().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.window.getScaledWidth() / (double) client.window.getWidth()));
|
||||
int slot_center_y = (int) (slot_center_y_scaled / ((double) client.window.getScaledHeight() / (double) client.window.getHeight()));
|
||||
double delta_x = slot_center_x - target_mouse_x;
|
||||
double delta_y = slot_center_y - target_mouse_y;
|
||||
|
||||
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;
|
||||
} else {
|
||||
mouse_speed_x = 0.F;
|
||||
mouse_speed_y = 0.F;
|
||||
}
|
||||
this.mouse_speed_x *= .75F;
|
||||
this.mouse_speed_y *= .75F;
|
||||
}
|
||||
} else {
|
||||
this.mouse_speed_x *= .1F;
|
||||
this.mouse_speed_y *= .1F;
|
||||
}
|
||||
} else {
|
||||
this.mouse_speed_x = 0.F;
|
||||
this.mouse_speed_y = 0.F;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user