Mixed input & Fix multiple issues

- Update to 1.20.4
- Touch can now be used in controller mode (especially nice on Steam Deck)
- Added option to choose between camera modes (Flat vs. Adaptive, addresses #232)
- Fixed broken button binding (#235)
This commit is contained in:
Martin Prokoph
2023-12-23 23:01:49 +01:00
parent afee0b407d
commit 6df3e4454b
32 changed files with 376 additions and 311 deletions

View File

@@ -27,6 +27,7 @@ import eu.midnightdust.midnightcontrols.client.mixin.KeyBindingIDAccessor;
import eu.midnightdust.midnightcontrols.client.ring.ButtonBindingRingAction;
import eu.midnightdust.midnightcontrols.client.ring.MidnightRing;
import dev.lambdaurora.spruceui.hud.HudManager;
import eu.midnightdust.midnightcontrols.client.touch.TouchInput;
import eu.midnightdust.midnightcontrols.client.util.RainbowColor;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
@@ -159,16 +160,16 @@ public class MidnightControlsClient extends MidnightControls implements ClientMo
GLFW.glfwSetJoystickCallback((jid, event) -> {
if (event == GLFW.GLFW_CONNECTED) {
var controller = Controller.byId(jid);
client.getToastManager().add(new SystemToast(SystemToast.Type.TUTORIAL_HINT, Text.translatable("midnightcontrols.controller.connected", jid),
client.getToastManager().add(new SystemToast(SystemToast.Type.PERIODIC_NOTIFICATION, Text.translatable("midnightcontrols.controller.connected", jid),
Text.literal(controller.getName())));
} else if (event == GLFW.GLFW_DISCONNECTED) {
client.getToastManager().add(new SystemToast(SystemToast.Type.TUTORIAL_HINT, Text.translatable("midnightcontrols.controller.disconnected", jid),
client.getToastManager().add(new SystemToast(SystemToast.Type.PERIODIC_NOTIFICATION, Text.translatable("midnightcontrols.controller.disconnected", jid),
null));
}
this.switchControlsMode();
});
} catch (Exception e) {e.printStackTrace();}
} catch (Exception e) {e.fillInStackTrace();}
MidnightControlsCompat.init(this);
}
@@ -229,6 +230,7 @@ public class MidnightControlsClient extends MidnightControls implements ClientMo
MidnightControlsConfig.save();
}
RainbowColor.tick();
TouchInput.tick();
}
/**

View File

@@ -18,6 +18,10 @@ import eu.midnightdust.midnightcontrols.MidnightControlsFeature;
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
import eu.midnightdust.midnightcontrols.client.controller.Controller;
import eu.midnightdust.midnightcontrols.client.controller.InputManager;
import eu.midnightdust.midnightcontrols.client.enums.CameraMode;
import eu.midnightdust.midnightcontrols.client.enums.ControllerType;
import eu.midnightdust.midnightcontrols.client.enums.HudSide;
import eu.midnightdust.midnightcontrols.client.enums.VirtualMouseSkin;
import eu.midnightdust.midnightcontrols.client.gui.RingScreen;
import eu.midnightdust.midnightcontrols.client.touch.TouchMode;
import net.minecraft.client.MinecraftClient;
@@ -36,79 +40,87 @@ import static org.lwjgl.glfw.GLFW.*;
* Represents MidnightControls configuration.
*/
public class MidnightControlsConfig extends MidnightConfig {
public static final String CONTROLLER = "controller";
public static final String TOUCH = "touch";
public static final String GAMEPLAY = "gameplay";
public static final String SCREENS = "screens";
public static final String VISUAL = "visual";
public static final String MISC = "misc";
public static boolean isEditing = false;
@Hidden @Entry public static int configVersion = 2;
// General
@Entry(category = "controller", name = "midnightcontrols.menu.controls_mode") public static ControlsMode controlsMode = ControlsMode.DEFAULT;
@Entry(category = "controller", name = "midnightcontrols.menu.auto_switch_mode") public static boolean autoSwitchMode = true;
@Entry(category = "misc", name = "Debug") public static boolean debug = false;
@Entry(category = CONTROLLER, name = "midnightcontrols.menu.controls_mode") public static ControlsMode controlsMode = ControlsMode.DEFAULT;
@Entry(category = CONTROLLER, name = "midnightcontrols.menu.auto_switch_mode") public static boolean autoSwitchMode = true;
@Entry(category = MISC, name = "Debug") public static boolean debug = false;
// HUD
@Entry(category = "visual", name = "midnightcontrols.menu.hud_enable") public static boolean hudEnable = true;
@Entry(category = "visual", name = "midnightcontrols.menu.hud_side") public static HudSide hudSide = HudSide.LEFT;
@Entry(category = "screens", name = "midnightcontrols.menu.move_chat") public static boolean moveChat = false;
@Entry(category = VISUAL, name = "midnightcontrols.menu.hud_enable") public static boolean hudEnable = true;
@Entry(category = VISUAL, name = "midnightcontrols.menu.hud_side") public static HudSide hudSide = HudSide.LEFT;
@Entry(category = SCREENS, name = "midnightcontrols.menu.move_chat") public static boolean moveChat = false;
// Gameplay
@Entry(category = "gameplay", name = "midnightcontrols.menu.analog_movement") public static boolean analogMovement = true;
@Entry(category = "gameplay", name = "midnightcontrols.menu.double_tap_to_sprint") public static boolean doubleTapToSprint = true;
@Entry(category = "gameplay", name = "midnightcontrols.menu.controller_toggle_sneak") public static boolean controllerToggleSneak = MinecraftClient.getInstance().options.getSneakToggled().getValue();
@Entry(category = "gameplay", name = "midnightcontrols.menu.controller_toggle_sprint") public static boolean controllerToggleSprint = MinecraftClient.getInstance().options.getSprintToggled().getValue();
@Entry(category = "gameplay", name = "midnightcontrols.menu.fast_block_placing") public static boolean fastBlockPlacing = false; // Disabled by default as this behaviour can be considered cheating on multiplayer servers.
@Entry(category = "gameplay", name = "midnightcontrols.menu.fly_drifting") public static boolean flyDrifting = true; // Enabled by default as disabling this behaviour can be considered cheating on multiplayer servers. It can also conflict with some other mods.
@Entry(category = "gameplay", name = "midnightcontrols.menu.fly_drifting_vertical") public static boolean verticalFlyDrifting = true; // Enabled by default as disabling this behaviour can be considered cheating on multiplayer servers.
@Entry(category = "gameplay", name = "midnightcontrols.menu.reacharound.horizontal") public static boolean horizontalReacharound = false; // Disabled by default as this behaviour can be considered cheating on multiplayer servers.
@Entry(category = "gameplay", name = "midnightcontrols.menu.reacharound.vertical") public static boolean verticalReacharound = false; // Disabled by default as this behaviour can be considered cheating on multiplayer servers.
@Entry(category = "visual", name = "Reacharound Outline") public static boolean shouldRenderReacharoundOutline = true;
@Entry(category = "visual", name = "Reacharound Outline Color", isColor = true) public static String reacharoundOutlineColorHex = "#ffffff";
@Entry(category = "visual", name = "Reacharound Outline Alpha", isSlider = true, min = 0, max = 255) public static int reacharoundOutlineColorAlpha = 102;
@Entry(category = "controller", name = "midnightcontrols.menu.right_dead_zone", isSlider = true, min = 0.05, max = 1) public static double rightDeadZone = 0.25;
@Entry(category = "controller", name = "midnightcontrols.menu.left_dead_zone", isSlider = true, min = 0.05, max = 1) public static double leftDeadZone = 0.25;
@Entry(category = "controller", name = "midnightcontrols.menu.invert_right_y_axis") public static boolean invertRightYAxis = false;
@Entry(category = "controller", name = "midnightcontrols.menu.invert_right_x_axis") public static boolean invertRightXAxis = false;
@Entry(category = "controller", name = "midnightcontrols.menu.rotation_speed", isSlider = true, min = 0, max = 100, precision = 10) public static double rotationSpeed = 35.0; //used for x-axis, name kept for compatibility
@Entry(category = "controller", name = "midnightcontrols.menu.y_axis_rotation_speed", isSlider = true, min = 0, max = 100, precision = 10) public static double yAxisRotationSpeed = rotationSpeed;
@Entry(category = "screens", name = "midnightcontrols.menu.mouse_speed", isSlider = true, min = 0, max = 150, precision = 10) public static double mouseSpeed = 25.0;
@Entry(category = "screens", name = "midnightcontrols.menu.joystick_as_mouse") public static boolean joystickAsMouse = false;
@Entry(category = "screens", name = "midnightcontrols.menu.eye_tracker_as_mouse") public static boolean eyeTrackerAsMouse = false;
@Entry(category = "screens", name = "midnightcontrols.menu.eye_tracker_deadzone", isSlider = true, min = 0, max = 0.4) public static double eyeTrackerDeadzone = 0.05;
@Entry(category = "controller", name = "midnightcontrols.menu.unfocused_input") public static boolean unfocusedInput = false;
@Entry(category = "screens", name = "midnightcontrols.menu.virtual_mouse") public static boolean virtualMouse = false;
@Entry(category = "screens", name = "midnightcontrols.menu.virtual_mouse.skin") public static VirtualMouseSkin virtualMouseSkin = VirtualMouseSkin.DEFAULT_LIGHT;
@Entry(category = "screens", name = "midnightcontrols.menu.hide_cursor") public static boolean hideNormalMouse = false;
@Entry(category = "controller", name = "Controller ID") @Hidden public static Object controllerID = 0;
@Entry(category = "controller", name = "2nd Controller ID") @Hidden public static Object secondControllerID = -1;
@Entry(category = "visual", name = "midnightcontrols.menu.controller_type") public static ControllerType controllerType = ControllerType.DEFAULT;
@Entry(category = "screens", name = "Mouse screens") public static List<String> mouseScreens = Lists.newArrayList("net.minecraft.client.gui.screen.advancement",
@Entry(category = GAMEPLAY, name = "midnightcontrols.menu.analog_movement") public static boolean analogMovement = true;
@Entry(category = GAMEPLAY, name = "midnightcontrols.menu.double_tap_to_sprint") public static boolean doubleTapToSprint = true;
@Entry(category = GAMEPLAY, name = "midnightcontrols.menu.controller_toggle_sneak") public static boolean controllerToggleSneak = MinecraftClient.getInstance().options.getSneakToggled().getValue();
@Entry(category = GAMEPLAY, name = "midnightcontrols.menu.controller_toggle_sprint") public static boolean controllerToggleSprint = MinecraftClient.getInstance().options.getSprintToggled().getValue();
@Entry(category = GAMEPLAY, name = "midnightcontrols.menu.fast_block_placing") public static boolean fastBlockPlacing = false; // Disabled by default as this behaviour can be considered cheating on multiplayer servers.
@Entry(category = GAMEPLAY, name = "midnightcontrols.menu.fly_drifting") public static boolean flyDrifting = true; // Enabled by default as disabling this behaviour can be considered cheating on multiplayer servers. It can also conflict with some other mods.
@Entry(category = GAMEPLAY, name = "midnightcontrols.menu.fly_drifting_vertical") public static boolean verticalFlyDrifting = true; // Enabled by default as disabling this behaviour can be considered cheating on multiplayer servers.
@Entry(category = GAMEPLAY, name = "midnightcontrols.menu.reacharound.horizontal") public static boolean horizontalReacharound = false; // Disabled by default as this behaviour can be considered cheating on multiplayer servers.
@Entry(category = GAMEPLAY, name = "midnightcontrols.menu.reacharound.vertical") public static boolean verticalReacharound = false; // Disabled by default as this behaviour can be considered cheating on multiplayer servers.
@Entry(category = VISUAL, name = "Reacharound Outline") public static boolean shouldRenderReacharoundOutline = true;
@Entry(category = VISUAL, name = "Reacharound Outline Color", isColor = true) public static String reacharoundOutlineColorHex = "#ffffff";
@Entry(category = VISUAL, name = "Reacharound Outline Alpha", isSlider = true, min = 0, max = 255) public static int reacharoundOutlineColorAlpha = 102;
@Entry(category = CONTROLLER, name = "midnightcontrols.menu.right_dead_zone", isSlider = true, min = 0.05, max = 1) public static double rightDeadZone = 0.25;
@Entry(category = CONTROLLER, name = "midnightcontrols.menu.left_dead_zone", isSlider = true, min = 0.05, max = 1) public static double leftDeadZone = 0.25;
@Entry(category = CONTROLLER, name = "midnightcontrols.menu.invert_right_y_axis") public static boolean invertRightYAxis = false;
@Entry(category = CONTROLLER, name = "midnightcontrols.menu.invert_right_x_axis") public static boolean invertRightXAxis = false;
@Entry(category = CONTROLLER, name = "midnightcontrols.menu.rotation_speed", isSlider = true, min = 0, max = 100, precision = 10) public static double rotationSpeed = 35.0; //used for x-axis, name kept for compatibility
@Entry(category = CONTROLLER, name = "midnightcontrols.menu.y_axis_rotation_speed", isSlider = true, min = 0, max = 100, precision = 10) public static double yAxisRotationSpeed = rotationSpeed;
@Entry(category = CONTROLLER, name = "midnightcontrols.menu.camera_mode") public static CameraMode cameraMode = CameraMode.FLAT;
@Entry(category = SCREENS, name = "midnightcontrols.menu.mouse_speed", isSlider = true, min = 0, max = 150, precision = 10) public static double mouseSpeed = 25.0;
@Entry(category = SCREENS, name = "midnightcontrols.menu.joystick_as_mouse") public static boolean joystickAsMouse = false;
@Entry(category = SCREENS, name = "midnightcontrols.menu.eye_tracker_as_mouse") public static boolean eyeTrackerAsMouse = false;
@Entry(category = SCREENS, name = "midnightcontrols.menu.eye_tracker_deadzone", isSlider = true, min = 0, max = 0.4) public static double eyeTrackerDeadzone = 0.05;
@Entry(category = CONTROLLER, name = "midnightcontrols.menu.unfocused_input") public static boolean unfocusedInput = false;
@Entry(category = SCREENS, name = "midnightcontrols.menu.virtual_mouse") public static boolean virtualMouse = false;
@Entry(category = SCREENS, name = "midnightcontrols.menu.virtual_mouse.skin") public static VirtualMouseSkin virtualMouseSkin = VirtualMouseSkin.DEFAULT_LIGHT;
@Entry(category = SCREENS, name = "midnightcontrols.menu.hide_cursor") public static boolean hideNormalMouse = false;
@Entry(category = CONTROLLER, name = "Controller ID") @Hidden public static Object controllerID = 0;
@Entry(category = CONTROLLER, name = "2nd Controller ID") @Hidden public static Object secondControllerID = -1;
@Entry(category = VISUAL, name = "midnightcontrols.menu.controller_type") public static ControllerType controllerType = ControllerType.DEFAULT;
@Entry(category = SCREENS, name = "Mouse screens") public static List<String> mouseScreens = Lists.newArrayList("net.minecraft.client.gui.screen.advancement",
"net.minecraft.class_457", "net.minecraft.class_408", "net.minecraft.class_3872", "me.flashyreese.mods.reeses_sodium_options.client.gui", "dev.emi.emi.screen",
"hardcorequesting.client.interfaces.GuiQuestBook", "hardcorequesting.client.interfaces.GuiReward", "hardcorequesting.client.interfaces.EditTrackerScreen",
"me.shedaniel.clothconfig2.gui.ClothConfigScreen", "com.mamiyaotaru.voxelmap.gui.GuiWaypoints", "com.mamiyaotaru.voxelmap.gui.GuiPersistentMap");
@Entry(category = "screens", name = "Arrow screens") public static List<String> arrowScreens = Lists.newArrayList(ChatScreen.class.getCanonicalName());
@Entry(category = "screens", name = "WASD screens") public static List<String> wasdScreens = Lists.newArrayList("com.ultreon.devices.core.Laptop");
@Entry(category = "touch", name = "Screens with close button") public static List<String> closeButtonScreens = Lists.newArrayList(ChatScreen.class.getCanonicalName(), AdvancementsScreen.class.getCanonicalName(), RingScreen.class.getCanonicalName());
@Entry(category = "touch", name = "midnightcontrols.menu.touch_speed", isSlider = true, min = 0, max = 150, precision = 10) public static double touchSpeed = 50.0;
@Entry(category = "touch", name = "midnightcontrols.menu.invert_touch") public static boolean invertTouch = false;
@Entry(category = "touch", name = "midnightcontrols.menu.touch_mode") public static TouchMode touchMode = TouchMode.CROSSHAIR;
@Entry(category = "touch", name = "midnightcontrols.menu.touch_break_delay", isSlider = true, min = 50, max = 500) public static int touchBreakDelay = 120;
@Entry(category = "touch", name = "midnightcontrols.menu.touch_transparency", isSlider = true, min = 0, max = 100) public static int touchTransparency = 75;
@Entry(category = "touch", name = "Touch Outline Color", isColor = true) public static String touchOutlineColorHex = "#ffffff";
@Entry(category = "touch", name = "Touch Outline Alpha", isSlider = true, min = 0, max = 255) public static int touchOutlineColorAlpha = 150;
@Entry(category = "touch", name = "Left Touch button bindings") public static List<String> leftTouchBinds = Lists.newArrayList("debug_screen", "screenshot","toggle_perspective");
@Entry(category = "touch", name = "Right Touch button bindings") public static List<String> rightTouchBinds = Lists.newArrayList("screenshot","toggle_perspective", "use");
@Entry(category = SCREENS, name = "Arrow screens") public static List<String> arrowScreens = Lists.newArrayList(ChatScreen.class.getCanonicalName());
@Entry(category = SCREENS, name = "WASD screens") public static List<String> wasdScreens = Lists.newArrayList("com.ultreon.devices.core.Laptop");
@Entry(category = TOUCH, name = "Screens with close button") public static List<String> closeButtonScreens = Lists.newArrayList(ChatScreen.class.getCanonicalName(), AdvancementsScreen.class.getCanonicalName(), RingScreen.class.getCanonicalName());
@Entry(category = TOUCH, name = "midnightcontrols.menu.touch_with_controller") public static boolean touchInControllerMode = false;
@Entry(category = TOUCH, name = "midnightcontrols.menu.touch_speed", isSlider = true, min = 0, max = 150, precision = 10) public static double touchSpeed = 50.0;
@Entry(category = TOUCH, name = "midnightcontrols.menu.invert_touch") public static boolean invertTouch = false;
@Entry(category = TOUCH, name = "midnightcontrols.menu.touch_mode") public static TouchMode touchMode = TouchMode.CROSSHAIR;
@Entry(category = TOUCH, name = "midnightcontrols.menu.touch_break_delay", isSlider = true, min = 50, max = 500) public static int touchBreakDelay = 120;
@Entry(category = TOUCH, name = "midnightcontrols.menu.touch_transparency", isSlider = true, min = 0, max = 100) public static int touchTransparency = 75;
@Entry(category = TOUCH, name = "Touch Outline Color", isColor = true) public static String touchOutlineColorHex = "#ffffff";
@Entry(category = TOUCH, name = "Touch Outline Alpha", isSlider = true, min = 0, max = 255) public static int touchOutlineColorAlpha = 150;
@Entry(category = TOUCH, name = "Left Touch button bindings") public static List<String> leftTouchBinds = Lists.newArrayList("debug_screen", "screenshot","toggle_perspective");
@Entry(category = TOUCH, name = "Right Touch button bindings") public static List<String> rightTouchBinds = Lists.newArrayList("screenshot","toggle_perspective", "use");
@Entry @Hidden public static Map<String, String> BINDING = new HashMap<>();
private static final Pattern BUTTON_BINDING_PATTERN = Pattern.compile("(-?\\d+)\\+?");
@Deprecated @Hidden @Entry public static double[] maxAnalogValues = new double[]{1, 1, 1, 1};
@Entry(category = "controller", name = "Max analog value: Left X", isSlider = true, min = .25f, max = 1.f) public static double maxAnalogValueLeftX = maxAnalogValues[0];
@Entry(category = "controller", name = "Max analog value: Left Y", isSlider = true, min = .25f, max = 1.f) public static double maxAnalogValueLeftY = maxAnalogValues[1];
@Entry(category = "controller", name = "Max analog value: Right X", isSlider = true, min = .25f, max = 1.f) public static double maxAnalogValueRightX = maxAnalogValues[2];
@Entry(category = "controller", name = "Max analog value: Right Y", isSlider = true, min = .25f, max = 1.f) public static double maxAnalogValueRightY = maxAnalogValues[3];
@Entry(category = "controller", name = "Trigger button fix") public static boolean triggerFix = false;
@Entry(category = "controller", name = "Excluded Keybindings") public static List<String> excludedKeybindings = Lists.newArrayList("key.forward", "key.left", "key.back", "key.right", "key.jump", "key.sneak", "key.sprint", "key.inventory",
@Entry(category = CONTROLLER, name = "Max analog value: Left X", isSlider = true, min = .25f, max = 1.f) public static double maxAnalogValueLeftX = maxAnalogValues[0];
@Entry(category = CONTROLLER, name = "Max analog value: Left Y", isSlider = true, min = .25f, max = 1.f) public static double maxAnalogValueLeftY = maxAnalogValues[1];
@Entry(category = CONTROLLER, name = "Max analog value: Right X", isSlider = true, min = .25f, max = 1.f) public static double maxAnalogValueRightX = maxAnalogValues[2];
@Entry(category = CONTROLLER, name = "Max analog value: Right Y", isSlider = true, min = .25f, max = 1.f) public static double maxAnalogValueRightY = maxAnalogValues[3];
@Entry(category = CONTROLLER, name = "Trigger button fix") public static boolean triggerFix = true;
@Entry(category = CONTROLLER, name = "Excluded Keybindings") public static List<String> excludedKeybindings = Lists.newArrayList("key.forward", "key.left", "key.back", "key.right", "key.jump", "key.sneak", "key.sprint", "key.inventory",
"key.swapOffhand", "key.drop", "key.use", "key.attack", "key.chat", "key.playerlist", "key.screenshot", "key.togglePerspective", "key.smoothCamera", "key.fullscreen", "key.saveToolbarActivator", "key.loadToolbarActivator",
"key.pickItem", "key.hotbar.1", "key.hotbar.2", "key.hotbar.3", "key.hotbar.4", "key.hotbar.5", "key.hotbar.6", "key.hotbar.7", "key.hotbar.8", "key.hotbar.9");
@Entry(category = "gameplay", name = "Enable Hints") public static boolean enableHints = true;
@Entry(category = "screens", name = "Enable Shortcut in Controls Options") public static boolean shortcutInControls = true;
@Entry(category = "misc", name = "Ring Bindings (WIP)") public static List<String> ringBindings = new ArrayList<>();
@Entry(category = "misc", name = "Ignored Unbound Keys") public static List<String> ignoredUnboundKeys = Lists.newArrayList("inventorytabs.key.next_tab");
@Entry(category = GAMEPLAY, name = "Enable Hints") public static boolean enableHints = true;
@Entry(category = SCREENS, name = "Enable Shortcut in Controls Options") public static boolean shortcutInControls = true;
@Entry(category = MISC, name = "Ring Bindings (WIP)") public static List<String> ringBindings = new ArrayList<>();
@Entry(category = MISC, name = "Ignored Unbound Keys") public static List<String> ignoredUnboundKeys = Lists.newArrayList("inventorytabs.key.next_tab");
@Entry @Hidden public static Map<String, Map<String, String>> controllerBindingProfiles = new HashMap<>();
private static Map<String, String> currentBindingProfile = new HashMap<>();
private static Controller prevController;

View File

@@ -17,6 +17,7 @@ import eu.midnightdust.midnightcontrols.client.compat.*;
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
import eu.midnightdust.midnightcontrols.client.controller.Controller;
import eu.midnightdust.midnightcontrols.client.controller.InputManager;
import eu.midnightdust.midnightcontrols.client.enums.CameraMode;
import eu.midnightdust.midnightcontrols.client.gui.RingScreen;
import eu.midnightdust.midnightcontrols.client.gui.TouchscreenOverlay;
import eu.midnightdust.midnightcontrols.client.gui.widget.ControllerControlsWidget;
@@ -31,6 +32,7 @@ import dev.lambdaurora.spruceui.widget.AbstractSprucePressableButtonWidget;
import dev.lambdaurora.spruceui.widget.SpruceElement;
import dev.lambdaurora.spruceui.widget.SpruceLabelWidget;
import dev.lambdaurora.spruceui.widget.container.SpruceParentWidget;
import eu.midnightdust.midnightcontrols.client.enums.ButtonState;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.Element;
@@ -149,8 +151,13 @@ public class MidnightInput {
if (allowInput)
InputManager.updateBindings(client);
if (this.controlsInput != null
&& InputManager.STATES.int2ObjectEntrySet().parallelStream().map(Map.Entry::getValue).allMatch(ButtonState::isUnpressed)) {
if (this.controlsInput != null) {
InputManager.STATES.forEach((num, button) -> {
if (button.isPressed()) System.out.println(num);
});
}
if (this.controlsInput != null && InputManager.STATES.int2ObjectEntrySet().parallelStream().map(Map.Entry::getValue).allMatch(ButtonState::isUnpressed)) {
System.out.println("finished");
if (this.controlsInput.focusedBinding != null && !this.controlsInput.waiting) {
int[] buttons = new int[this.controlsInput.currentButtons.size()];
for (int i = 0; i < this.controlsInput.currentButtons.size(); i++)
@@ -490,6 +497,7 @@ public class MidnightInput {
{
boolean currentPlusState = value > getDeadZoneValue(axis);
boolean currentMinusState = value < -getDeadZoneValue(axis);
if (axis == GLFW_GAMEPAD_AXIS_LEFT_TRIGGER || axis == GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER) currentMinusState = false;
if (!MidnightControlsConfig.analogMovement && (axis == GLFW_GAMEPAD_AXIS_LEFT_X || axis == GLFW_GAMEPAD_AXIS_LEFT_Y)) {
currentPlusState = asButtonState == 1;
currentMinusState = asButtonState == 2;
@@ -786,6 +794,28 @@ public class MidnightInput {
* @param state the state
*/
public void handleLook(@NotNull MinecraftClient client, int axis, float value, int state) {
if (client.player == null) return;
// Handles the look direction.
if (MidnightControlsConfig.cameraMode == CameraMode.FLAT) {
double powValue = Math.pow(value, 2.0);
if (axis == GLFW_GAMEPAD_AXIS_RIGHT_Y) {
if (state == 2) {
this.targetPitch = -MidnightControlsConfig.getRightYAxisSign() * (MidnightControlsConfig.yAxisRotationSpeed * powValue) * 0.11D;
} else if (state == 1) {
this.targetPitch = MidnightControlsConfig.getRightYAxisSign() * (MidnightControlsConfig.yAxisRotationSpeed * powValue) * 0.11D;
}
}
if (axis == GLFW_GAMEPAD_AXIS_RIGHT_X) {
if (state == 2) {
this.targetYaw = -MidnightControlsConfig.getRightXAxisSign() * (MidnightControlsConfig.rotationSpeed * powValue) * 0.11D;
} else if (state == 1) {
this.targetYaw = MidnightControlsConfig.getRightXAxisSign() * (MidnightControlsConfig.rotationSpeed * powValue) * 0.11D;
}
}
return;
}
// Code below runs for adaptive camera mode
// Handles the look direction.
if (axis == GLFW_GAMEPAD_AXIS_RIGHT_X) {
xValue = value;

View File

@@ -9,12 +9,10 @@
package eu.midnightdust.midnightcontrols.client.controller;
import eu.midnightdust.midnightcontrols.client.ButtonState;
import eu.midnightdust.midnightcontrols.client.enums.ButtonState;
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
import eu.midnightdust.midnightcontrols.client.gui.RingScreen;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.hud.DebugHud;
import net.minecraft.client.gui.hud.InGameHud;
import net.minecraft.client.option.GameOptions;
import net.minecraft.client.option.KeyBinding;
import net.minecraft.client.resource.language.I18n;

View File

@@ -180,7 +180,7 @@ public record Controller(int id) implements Nameable {
var string = l == 0L ? "" : MemoryUtil.memUTF8(l);
var client = MinecraftClient.getInstance();
if (client != null) {
client.getToastManager().add(SystemToast.create(client, SystemToast.Type.TUTORIAL_HINT,
client.getToastManager().add(SystemToast.create(client, SystemToast.Type.PERIODIC_NOTIFICATION,
Text.translatable("midnightcontrols.controller.mappings.error"), Text.literal(string)));
MidnightControls.get().log(I18n.translate("midnightcontrols.controller.mappings.error")+string);
}

View File

@@ -11,7 +11,7 @@ package eu.midnightdust.midnightcontrols.client.controller;
import com.google.common.collect.Lists;
import eu.midnightdust.lib.util.PlatformFunctions;
import eu.midnightdust.midnightcontrols.client.ButtonState;
import eu.midnightdust.midnightcontrols.client.enums.ButtonState;
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
import eu.midnightdust.midnightcontrols.client.MidnightInput;

View File

@@ -10,7 +10,7 @@
package eu.midnightdust.midnightcontrols.client.controller;
import eu.midnightdust.midnightcontrols.ControlsMode;
import eu.midnightdust.midnightcontrols.client.ButtonState;
import eu.midnightdust.midnightcontrols.client.enums.ButtonState;
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
import eu.midnightdust.midnightcontrols.client.util.MouseAccessor;
import it.unimi.dsi.fastutil.ints.*;
@@ -27,7 +27,6 @@ import org.lwjgl.glfw.GLFW;
import java.util.*;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**

View File

@@ -9,21 +9,12 @@
package eu.midnightdust.midnightcontrols.client.controller;
import eu.midnightdust.midnightcontrols.client.ButtonState;
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
import eu.midnightdust.midnightcontrols.client.enums.ButtonState;
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
import eu.midnightdust.midnightcontrols.client.util.MathUtil;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.input.Input;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.client.tutorial.MovementTutorialStepHandler;
import net.minecraft.client.util.InputUtil;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.enchantment.Enchantments;
import net.minecraft.enchantment.SoulSpeedEnchantment;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.nbt.NbtList;
import net.minecraft.nbt.scanner.SimpleNbtScanner;
import net.minecraft.util.math.MathHelper;
import org.jetbrains.annotations.NotNull;

View File

@@ -9,7 +9,7 @@
package eu.midnightdust.midnightcontrols.client.controller;
import eu.midnightdust.midnightcontrols.client.ButtonState;
import eu.midnightdust.midnightcontrols.client.enums.ButtonState;
import eu.midnightdust.midnightcontrols.client.util.KeyBindingAccessor;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.option.StickyKeyBinding;

View File

@@ -7,7 +7,7 @@
* see the LICENSE file.
*/
package eu.midnightdust.midnightcontrols.client;
package eu.midnightdust.midnightcontrols.client.enums;
/**
* Represents a button state.

View File

@@ -0,0 +1,5 @@
package eu.midnightdust.midnightcontrols.client.enums;
public enum CameraMode {
FLAT, ADAPTIVE
}

View File

@@ -7,7 +7,7 @@
* see the LICENSE file.
*/
package eu.midnightdust.midnightcontrols.client;
package eu.midnightdust.midnightcontrols.client.enums;
import net.minecraft.text.Text;
import org.aperlambda.lambdacommon.utils.Nameable;

View File

@@ -7,7 +7,7 @@
* see the LICENSE file.
*/
package eu.midnightdust.midnightcontrols.client;
package eu.midnightdust.midnightcontrols.client.enums;
import net.minecraft.text.Text;
import org.aperlambda.lambdacommon.utils.Nameable;

View File

@@ -7,7 +7,7 @@
* see the LICENSE file.
*/
package eu.midnightdust.midnightcontrols.client;
package eu.midnightdust.midnightcontrols.client.enums;
import net.minecraft.text.Text;
import org.aperlambda.lambdacommon.utils.Nameable;

View File

@@ -63,7 +63,7 @@ public class MappingsStringInputWidget extends SpruceContainerWidget {
fw.close();
} catch (IOException e) {
if (this.client != null)
this.client.getToastManager().add(SystemToast.create(this.client, SystemToast.Type.TUTORIAL_HINT,
this.client.getToastManager().add(SystemToast.create(this.client, SystemToast.Type.PERIODIC_NOTIFICATION,
Text.translatable("midnightcontrols.controller.mappings.error.write"), Text.empty()));
e.printStackTrace();
}

View File

@@ -11,7 +11,7 @@ package eu.midnightdust.midnightcontrols.client.gui;
import eu.midnightdust.midnightcontrols.ControlsMode;
import eu.midnightdust.midnightcontrols.MidnightControlsConstants;
import eu.midnightdust.midnightcontrols.client.HudSide;
import eu.midnightdust.midnightcontrols.client.enums.HudSide;
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
import eu.midnightdust.midnightcontrols.client.compat.MidnightControlsCompat;

View File

@@ -10,7 +10,7 @@
package eu.midnightdust.midnightcontrols.client.gui;
import com.mojang.blaze3d.systems.RenderSystem;
import eu.midnightdust.midnightcontrols.client.ControllerType;
import eu.midnightdust.midnightcontrols.client.enums.ControllerType;
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
import eu.midnightdust.midnightcontrols.client.MidnightInput;

View File

@@ -33,7 +33,7 @@ public class ReloadControllerMappingsOption {
Controller.updateMappings();
if (client.currentScreen instanceof MidnightControlsSettingsScreen)
client.currentScreen.init(client, client.getWindow().getScaledWidth(), client.getWindow().getScaledHeight());
client.getToastManager().add(SystemToast.create(client, SystemToast.Type.TUTORIAL_HINT,
client.getToastManager().add(SystemToast.create(client, SystemToast.Type.PERIODIC_NOTIFICATION,
Text.translatable("midnightcontrols.controller.mappings.updated"), Text.empty()));
}, Text.translatable("midnightcontrols.tooltip.reload_controller_mappings"));
}

View File

@@ -13,8 +13,8 @@ import dev.lambdaurora.spruceui.Position;
import dev.lambdaurora.spruceui.widget.SpruceButtonWidget;
import eu.midnightdust.lib.util.PlatformFunctions;
import eu.midnightdust.midnightcontrols.MidnightControlsConstants;
import eu.midnightdust.midnightcontrols.client.ButtonState;
import eu.midnightdust.midnightcontrols.client.HudSide;
import eu.midnightdust.midnightcontrols.client.enums.ButtonState;
import eu.midnightdust.midnightcontrols.client.enums.HudSide;
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
import eu.midnightdust.midnightcontrols.client.compat.EmotecraftCompat;
@@ -24,7 +24,6 @@ import eu.midnightdust.midnightcontrols.client.touch.gui.ItemUseButtonWidget;
import eu.midnightdust.midnightcontrols.client.touch.gui.SilentTexturedButtonWidget;
import eu.midnightdust.midnightcontrols.client.touch.TouchUtils;
import eu.midnightdust.midnightcontrols.client.util.KeyBindingAccessor;
import net.minecraft.block.BlockState;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.screen.*;
import net.minecraft.client.gui.screen.ingame.InventoryScreen;
@@ -37,9 +36,6 @@ import net.minecraft.item.*;
import net.minecraft.network.packet.c2s.play.PlayerActionC2SPacket;
import net.minecraft.text.Text;
import net.minecraft.util.*;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.hit.EntityHitResult;
import net.minecraft.util.hit.HitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import org.jetbrains.annotations.NotNull;
@@ -75,8 +71,6 @@ public class TouchscreenOverlay extends Screen {
private SilentTexturedButtonWidget endSneakButton;
private int flyButtonEnableTicks = 0;
private int forwardButtonTick = 0;
public long clickStartTime;
public HitResult firstHitResult = null;
public static TouchscreenOverlay instance;
public TouchscreenOverlay(@NotNull MidnightControlsClient mod) {
@@ -303,7 +297,7 @@ public class TouchscreenOverlay extends Screen {
if (binding == null) continue;
boolean hasTexture = client.getGuiAtlasManager().getSprite(new Identifier(MidnightControlsConstants.NAMESPACE, "binding/"+bindName)) != missingSprite;
if (MidnightControlsConfig.debug) System.out.println(left +" "+new Identifier(MidnightControlsConstants.NAMESPACE, "binding/"+bindName)+" "+ hasTexture);
var button = TextIconButtonWidget.builder(Text.translatable("binding.getTranslationKey()"), b -> binding.handle(client, 1, ButtonState.PRESS), hasTexture)
var button = TextIconButtonWidget.builder(Text.translatable(binding.getTranslationKey()), b -> binding.handle(client, 1, ButtonState.PRESS), hasTexture)
.texture(hasTexture ? new Identifier(MidnightControlsConstants.NAMESPACE, "binding/"+bindName) : emptySprite, 20, 20).dimension(20, 20).build();
button.setPosition(left ? (3+(i*23)) : this.width-(23+(i*23)), 3);
button.setAlpha(MidnightControlsConfig.touchTransparency / 100f);
@@ -316,7 +310,8 @@ public class TouchscreenOverlay extends Screen {
this.swapHandsButton.setAlpha(transparency);
this.jumpButton.setAlpha(transparency);
this.flyButton.setAlpha(transparency);
this.flyUpButton.setAlpha(transparency);this.useButton.setAlpha(Math.min(transparency+0.1f, 1.0f));
this.flyUpButton.setAlpha(transparency);
this.useButton.setAlpha(Math.min(transparency+0.1f, 1.0f));
this.flyDownButton.setAlpha(transparency);
this.startSneakButton.setAlpha(transparency);
this.endSneakButton.setAlpha(transparency);
@@ -346,104 +341,6 @@ public class TouchscreenOverlay extends Screen {
}
this.useButton.setVisible(client.player.getMainHandStack() != null && (client.player.getMainHandStack().getUseAction() != UseAction.NONE || client.player.getMainHandStack().getItem() instanceof ArmorItem) && !TouchUtils.hasInWorldUseAction(client.player.getMainHandStack()));
this.updateJumpButtons();
double scaleFactor = client.getWindow().getScaleFactor();
if (clickStartTime > 0 && System.currentTimeMillis() - clickStartTime >= MidnightControlsConfig.touchBreakDelay) this.mouseHeldDown(client.mouse.getX() / scaleFactor, client.mouse.getY() / scaleFactor);
else client.interactionManager.cancelBlockBreaking();
}
@Override
public boolean mouseClicked(double mouseX, double mouseY, int button) {
int centerX = this.width / 2;
if (mouseY >= (double) (this.height - 22) && this.client != null && this.client.player != null && mouseX >= (double) (centerX - 90) && mouseX <= (double) (centerX + 90)) {
for (int slot = 0; slot < 9; ++slot) {
int slotX = centerX - 90 + slot * 20 + 2;
if (mouseX >= (double) slotX && mouseX <= (double) (slotX + 20)) {
this.client.player.getInventory().selectedSlot = slot;
return true;
}
}
} else {
clickStartTime = System.currentTimeMillis();
boolean bl = super.mouseClicked(mouseX, mouseY, button);
if (!bl) firstHitResult = TouchUtils.getTargettedObject(mouseX, mouseY);
return bl;
}
return super.mouseClicked(mouseX, mouseY, button);
}
@Override
public boolean mouseReleased(double mouseX, double mouseY, int button) {
firstHitResult = null;
if (!super.mouseReleased(mouseX, mouseY, button) && System.currentTimeMillis() - clickStartTime < 200) {
assert client != null;
assert client.player != null;
assert client.world != null;
assert client.interactionManager != null;
clickStartTime = -1;
if (client.player.getMainHandStack() != null && TouchUtils.hasInWorldUseAction(client.player.getMainHandStack())) {
client.interactionManager.stopUsingItem(client.player);
return true;
}
HitResult result = TouchUtils.getTargettedObject(mouseX, mouseY);
if (result == null) return false;
if (result instanceof BlockHitResult blockHit) {
BlockPos blockPos = blockHit.getBlockPos().offset(blockHit.getSide());
BlockState state = client.world.getBlockState(blockPos);
if (client.world.isAir(blockPos) || state.isReplaceable()) {
ItemStack stackInHand = client.player.getMainHandStack();
int previousStackCount = stackInHand.getCount();
var interaction = client.interactionManager.interactBlock(client.player, client.player.getActiveHand(), blockHit);
if (interaction.isAccepted()) {
if (interaction.shouldSwingHand()) {
client.player.swingHand(client.player.preferredHand);
if (!stackInHand.isEmpty() && (stackInHand.getCount() != previousStackCount || client.interactionManager.hasCreativeInventory())) {
client.gameRenderer.firstPersonRenderer.resetEquipProgress(client.player.preferredHand);
}
}
return true;
}
}
}
if (result instanceof EntityHitResult entityHit) {
client.interactionManager.attackEntity(client.player, entityHit.getEntity());
client.player.swingHand(Hand.MAIN_HAND);
}
}
clickStartTime = -1;
return false;
}
public void mouseHeldDown(double mouseX, double mouseY) {
assert client != null;
assert client.player != null;
assert client.interactionManager != null;
if (!isDragging()) {
if (client.player.getMainHandStack() != null && TouchUtils.hasInWorldUseAction(client.player.getMainHandStack())) {
client.interactionManager.interactItem(client.player, client.player.getActiveHand());
return;
}
HitResult result = TouchUtils.getTargettedObject(mouseX, mouseY);
if (result == null || firstHitResult == null) return;
if (result instanceof BlockHitResult blockHit && firstHitResult instanceof BlockHitResult firstBlock && blockHit.getBlockPos().equals(firstBlock.getBlockPos())) {
if (MidnightControlsConfig.debug) System.out.println(blockHit.getBlockPos().toString());
if (client.interactionManager.updateBlockBreakingProgress(blockHit.getBlockPos(), blockHit.getSide())) {
client.particleManager.addBlockBreakingParticles(blockHit.getBlockPos(), blockHit.getSide());
client.player.swingHand(Hand.MAIN_HAND);
} else client.interactionManager.cancelBlockBreaking();
firstHitResult = TouchUtils.getTargettedObject(mouseX, mouseY);
}
else if (result instanceof EntityHitResult entityHit && firstHitResult instanceof EntityHitResult firstEntity && entityHit.getEntity().getUuid().compareTo(firstEntity.getEntity().getUuid()) == 0) {
if (client.interactionManager.interactEntity(client.player, entityHit.getEntity(), client.player.getActiveHand()) == ActionResult.SUCCESS) {
client.player.swingHand(Hand.MAIN_HAND);
}
firstHitResult = TouchUtils.getTargettedObject(mouseX, mouseY);
}
}
}
@Override
@@ -460,23 +357,12 @@ public class TouchscreenOverlay extends Screen {
if (deltaX > 0.01)
this.mod.input.handleLook(this.client, GLFW_GAMEPAD_AXIS_RIGHT_X, (float) Math.abs((deltaX / 3.0)*MidnightControlsConfig.touchSpeed/100), 2);
else this.mod.input.handleLook(this.client, GLFW_GAMEPAD_AXIS_RIGHT_X, (float) Math.abs((deltaX / 3.0)*MidnightControlsConfig.touchSpeed/100), 1);
HitResult result = TouchUtils.getTargettedObject(mouseX, mouseY);
if (result != null && firstHitResult != null) {
if (result instanceof BlockHitResult blockHit && firstHitResult instanceof BlockHitResult firstBlock && !blockHit.getBlockPos().equals(firstBlock.getBlockPos())) {
firstHitResult = null;
} else if (result instanceof EntityHitResult entityHit && firstHitResult instanceof EntityHitResult firstEntity && entityHit.getEntity().getUuid().compareTo(firstEntity.getEntity().getUuid()) != 0) {
firstHitResult = null;
}
}
}
return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY);
}
@Override
public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
//client.currentScreen = null;
KeyBinding.onKeyPressed(InputUtil.fromKeyCode(keyCode, scanCode));
super.keyPressed(keyCode,scanCode,modifiers);
return true;
}

View File

@@ -39,24 +39,15 @@ import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
@Mixin(MinecraftClient.class)
public abstract class MinecraftClientMixin {
@Shadow
@Nullable
public HitResult crosshairTarget;
@Shadow @Nullable public HitResult crosshairTarget;
@Shadow
@Nullable
public ClientPlayerEntity player;
@Shadow @Nullable public ClientPlayerEntity player;
@Shadow
@Nullable
public ClientPlayerInteractionManager interactionManager;
@Shadow @Nullable public ClientPlayerInteractionManager interactionManager;
@Shadow
@Final
public GameRenderer gameRenderer;
@Shadow @Final public GameRenderer gameRenderer;
@Shadow
private int itemUseCooldown;
@Shadow private int itemUseCooldown;
@Shadow public abstract BufferBuilderStorage getBufferBuilders();

View File

@@ -0,0 +1,15 @@
package eu.midnightdust.midnightcontrols.client.mixin;
import net.minecraft.client.Mouse;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import org.spongepowered.asm.mixin.gen.Invoker;
@Mixin(Mouse.class)
public interface MouseAccessor {
@Accessor
void setLeftButtonClicked(boolean value);
@Invoker("onCursorPos")
void midnightcontrols$onCursorPos(long window, double x, double y);
}

View File

@@ -12,104 +12,111 @@ package eu.midnightdust.midnightcontrols.client.mixin;
import eu.midnightdust.midnightcontrols.ControlsMode;
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
import eu.midnightdust.midnightcontrols.client.gui.TouchscreenOverlay;
import eu.midnightdust.midnightcontrols.client.touch.TouchInput;
import eu.midnightdust.midnightcontrols.client.touch.TouchUtils;
import eu.midnightdust.midnightcontrols.client.util.MouseAccessor;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.Mouse;
import net.minecraft.client.option.KeyBinding;
import net.minecraft.client.util.GlfwUtil;
import net.minecraft.client.util.SmoothUtil;
import org.lwjgl.glfw.GLFW;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.gen.Accessor;
import org.spongepowered.asm.mixin.gen.Invoker;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import eu.midnightdust.midnightcontrols.client.mouse.EyeTrackerHandler;
import static org.lwjgl.glfw.GLFW.GLFW_CURSOR;
import static org.lwjgl.glfw.GLFW.GLFW_CURSOR_HIDDEN;
import static org.lwjgl.glfw.GLFW.*;
/**
* Adds extra access to the mouse.
*/
@Mixin(Mouse.class)
public abstract class MouseMixin implements MouseAccessor {
@Shadow
@Final
private MinecraftClient client;
@Shadow @Final private MinecraftClient client;
@Shadow
private double y;
@Shadow private double y;
@Shadow
private double cursorDeltaX;
@Shadow private double cursorDeltaX;
@Shadow
private double cursorDeltaY;
@Shadow private double cursorDeltaY;
@Shadow
private double x;
@Shadow private double x;
@Shadow
private boolean cursorLocked;
@Shadow private boolean cursorLocked;
@Shadow
private boolean hasResolutionChanged;
@Shadow private boolean hasResolutionChanged;
@Shadow
private double lastMouseUpdateTime;
@Shadow private double lastMouseUpdateTime;
@Shadow
@Final
private SmoothUtil cursorXSmoother;
@Shadow @Final private SmoothUtil cursorXSmoother;
@Shadow
@Final
private SmoothUtil cursorYSmoother;
@Shadow @Final private SmoothUtil cursorYSmoother;
@Shadow private boolean leftButtonClicked;
@Accessor
public abstract void setLeftButtonClicked(boolean value);
@Shadow private int activeButton;
@Invoker("onCursorPos")
public abstract void midnightcontrols$onCursorPos(long window, double x, double y);
@Shadow private double glfwTime;
@Inject(method = "onMouseButton", at = @At(value = "TAIL"))
private void onMouseBackButton(long window, int button, int action, int mods, CallbackInfo ci) {
if (action == 1 && button == GLFW.GLFW_MOUSE_BUTTON_4 && MinecraftClient.getInstance().currentScreen != null) {
if (MidnightControlsClient.get().input.tryGoBack(MinecraftClient.getInstance().currentScreen)) {
action = 0;
}
@Inject(method = "onMouseButton", at = @At(value = "HEAD"), cancellable = true)
private void midnightcontrols$onMouseButton(long window, int button, int action, int mods, CallbackInfo ci) {
if (window != this.client.getWindow().getHandle()) return;
if (action == 1 && button == GLFW.GLFW_MOUSE_BUTTON_4 && client.currentScreen != null) {
MidnightControlsClient.get().input.tryGoBack(client.currentScreen);
}
else if ((client.currentScreen == null || client.currentScreen instanceof TouchscreenOverlay) && client.player != null && button == GLFW_MOUSE_BUTTON_1) {
double mouseX = x / client.getWindow().getScaleFactor();
double mouseY = y / client.getWindow().getScaleFactor();
int centerX = client.getWindow().getScaledWidth() / 2;
if (action == 1 && mouseY >= (double) (client.getWindow().getScaledHeight() - 22) && mouseX >= (double) (centerX - 90) && mouseX <= (double) (centerX + 90)) {
for (int slot = 0; slot < 9; ++slot) {
int slotX = centerX - 90 + slot * 20 + 2;
if (mouseX >= (double) slotX && mouseX <= (double) (slotX + 20)) {
client.player.getInventory().selectedSlot = slot;
ci.cancel();
return;
}
}
}
if (action == 1) {
TouchInput.clickStartTime = System.currentTimeMillis();
boolean bl = false;
if (client.currentScreen instanceof TouchscreenOverlay overlay) bl = overlay.mouseClicked(mouseX, mouseY, button);
if (!bl) TouchInput.firstHitResult = TouchUtils.getTargettedObject(mouseX, mouseY);
ci.cancel();
}
else if (TouchInput.mouseReleased(mouseX, mouseY, button)) ci.cancel();
}
}
@Inject(method = "onCursorPos", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/profiler/Profiler;push(Ljava/lang/String;)V", shift = At.Shift.BEFORE))
private void midnightcontrols$onCursorDrag(long window, double x, double y, CallbackInfo ci) {
TouchInput.dragging = this.activeButton == GLFW_MOUSE_BUTTON_1 && this.glfwTime > 0.0;
}
@Inject(method = "isCursorLocked", at = @At("HEAD"), cancellable = true)
private void isCursorLocked(CallbackInfoReturnable<Boolean> ci) {
private void midnightcontrols$isCursorLocked(CallbackInfoReturnable<Boolean> ci) {
if (this.client.currentScreen == null) {
if (MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER && MidnightControlsConfig.virtualMouse) {
//ci.setReturnValue(true);
ci.cancel();
}
}
}
@Inject(method = "lockCursor", at = @At("HEAD"), cancellable = true)
private void onCursorLocked(CallbackInfo ci) {
if ((MidnightControlsConfig.eyeTrackerAsMouse && client.isWindowFocused() && !this.cursorLocked)
|| MidnightControlsConfig.controlsMode == ControlsMode.TOUCHSCREEN
|| (MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER && MidnightControlsConfig.virtualMouse))
private void midnightcontrols$onCursorLocked(CallbackInfo ci) {
if (MidnightControlsConfig.controlsMode == ControlsMode.TOUCHSCREEN || (MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER && MidnightControlsConfig.virtualMouse))
ci.cancel();
}
@Inject(method = "updateMouse", at = @At("HEAD"), cancellable = true)
private void updateMouse(CallbackInfo ci) {
private void midnightcontrols$updateMouse(CallbackInfo ci) {
if (MidnightControlsConfig.eyeTrackerAsMouse && cursorLocked && client.isWindowFocused()) {
//Eye Tracking is only for the camera controlling cursor, we need the normal cursor everywhere else.
// Eye Tracking is only for the camera controlling cursor, we need the normal cursor everywhere else.
if (!client.options.smoothCameraEnabled) {
cursorXSmoother.clear();
cursorYSmoother.clear();
@@ -121,17 +128,16 @@ public abstract class MouseMixin implements MouseAccessor {
cursorDeltaY = 0.0;
ci.cancel();
}
if ((MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER && MidnightControlsConfig.touchInControllerMode) && client.isWindowFocused()) {
ci.cancel();
}
}
@Inject(method = "lockCursor", at = @At("HEAD"), cancellable = true)
private void lockCursor(CallbackInfo ci) {
if (MidnightControlsConfig.eyeTrackerAsMouse && client.isWindowFocused() && !this.cursorLocked) {
if (!MinecraftClient.IS_SYSTEM_MAC) {
KeyBinding.updatePressedStates();
}
@Inject(method = "lockCursor", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/util/InputUtil;setCursorParameters(JIDD)V",shift = At.Shift.BEFORE), cancellable = true)
private void midnightcontrols$lockCursor(CallbackInfo ci) {
if ((MidnightControlsConfig.touchInControllerMode || MidnightControlsConfig.eyeTrackerAsMouse)) {
//In eye tracking mode, we cannot have the cursor locked to the center.
GLFW.glfwSetInputMode(client.getWindow().getHandle(), GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
cursorLocked = true; //The game uses this flag for other gameplay checks
client.setScreen(null);
hasResolutionChanged = true;
ci.cancel();

View File

@@ -2,7 +2,7 @@ package eu.midnightdust.midnightcontrols.client.mixin;
import dev.lambdaurora.spruceui.Position;
import eu.midnightdust.midnightcontrols.ControlsMode;
import eu.midnightdust.midnightcontrols.client.ButtonState;
import eu.midnightdust.midnightcontrols.client.enums.ButtonState;
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
import eu.midnightdust.midnightcontrols.client.controller.InputHandlers;

View File

@@ -13,7 +13,7 @@ import eu.midnightdust.lib.util.MidnightColorUtil;
import eu.midnightdust.midnightcontrols.ControlsMode;
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
import eu.midnightdust.midnightcontrols.client.gui.TouchscreenOverlay;
import eu.midnightdust.midnightcontrols.client.touch.TouchInput;
import eu.midnightdust.midnightcontrols.client.touch.TouchMode;
import eu.midnightdust.midnightcontrols.client.util.RainbowColor;
import net.minecraft.block.ShapeContext;
@@ -80,16 +80,17 @@ public abstract class WorldRendererMixin {
)
private void onOutlineRender(MatrixStack matrices, float tickDelta, long limitTime, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer,
LightmapTextureManager lightmapTextureManager, Matrix4f matrix4f, CallbackInfo ci) {
if (MidnightControlsConfig.controlsMode == ControlsMode.TOUCHSCREEN && MidnightControlsConfig.touchMode == TouchMode.FINGER_POS && TouchscreenOverlay.instance != null) {
if (((MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER && MidnightControlsConfig.touchInControllerMode) || MidnightControlsConfig.controlsMode == ControlsMode.TOUCHSCREEN)
&& MidnightControlsConfig.touchMode == TouchMode.FINGER_POS) {
this.renderFingerOutline(matrices, camera);
}
this.renderReacharoundOutline(matrices, camera);
}
@Unique
private void renderFingerOutline(MatrixStack matrices, Camera camera) {
if (TouchscreenOverlay.instance.firstHitResult == null || TouchscreenOverlay.instance.firstHitResult.getType() != HitResult.Type.BLOCK)
if (TouchInput.firstHitResult == null || TouchInput.firstHitResult.getType() != HitResult.Type.BLOCK)
return;
BlockHitResult result = (BlockHitResult) TouchscreenOverlay.instance.firstHitResult;
BlockHitResult result = (BlockHitResult) TouchInput.firstHitResult;
var blockPos = result.getBlockPos();
if (this.world.getWorldBorder().contains(blockPos) && this.client.player != null) {
var outlineShape = this.world.getBlockState(blockPos).getOutlineShape(this.client.world, blockPos, ShapeContext.of(camera.getFocusedEntity()));

View File

@@ -10,16 +10,13 @@
package eu.midnightdust.midnightcontrols.client.ring;
import com.electronwill.nightconfig.core.Config;
import eu.midnightdust.midnightcontrols.client.ButtonState;
import eu.midnightdust.midnightcontrols.client.enums.ButtonState;
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
import eu.midnightdust.midnightcontrols.client.util.KeyBindingAccessor;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.option.KeyBinding;
import net.minecraft.client.option.StickyKeyBinding;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.text.OrderedText;
import net.minecraft.text.Text;
import org.jetbrains.annotations.NotNull;

View File

@@ -0,0 +1,111 @@
package eu.midnightdust.midnightcontrols.client.touch;
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
import eu.midnightdust.midnightcontrols.client.gui.TouchscreenOverlay;
import net.minecraft.block.BlockState;
import net.minecraft.client.MinecraftClient;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.hit.EntityHitResult;
import net.minecraft.util.hit.HitResult;
import net.minecraft.util.math.BlockPos;
public class TouchInput {
private static final MinecraftClient client = MinecraftClient.getInstance();
public static long clickStartTime;
public static HitResult firstHitResult = null;
public static boolean dragging = false;
public static void tick() {
if (client.currentScreen != null && !(client.currentScreen instanceof TouchscreenOverlay)) return;
double scaleFactor = client.getWindow().getScaleFactor();
if (clickStartTime > 0 && System.currentTimeMillis() - clickStartTime >= MidnightControlsConfig.touchBreakDelay) {
mouseHeldDown(client.mouse.getX() / scaleFactor, client.mouse.getY() / scaleFactor);
}
else {
if (client.interactionManager != null) client.interactionManager.cancelBlockBreaking();
}
}
public static void mouseHeldDown(double mouseX, double mouseY) {
assert client != null;
assert client.player != null;
assert client.interactionManager != null;
if (!dragging) {
if (client.player.getMainHandStack() != null && TouchUtils.hasInWorldUseAction(client.player.getMainHandStack())) {
client.interactionManager.interactItem(client.player, client.player.getActiveHand());
return;
}
HitResult result = TouchUtils.getTargettedObject(mouseX, mouseY);
if (result == null || firstHitResult == null) return;
if (result instanceof BlockHitResult blockHit && firstHitResult instanceof BlockHitResult firstBlock && blockHit.getBlockPos().equals(firstBlock.getBlockPos())) {
if (MidnightControlsConfig.debug) System.out.println(blockHit.getBlockPos().toString());
if (client.interactionManager.updateBlockBreakingProgress(blockHit.getBlockPos(), blockHit.getSide())) {
client.particleManager.addBlockBreakingParticles(blockHit.getBlockPos(), blockHit.getSide());
client.player.swingHand(Hand.MAIN_HAND);
} else client.interactionManager.cancelBlockBreaking();
firstHitResult = TouchUtils.getTargettedObject(mouseX, mouseY);
}
else if (result instanceof EntityHitResult entityHit && firstHitResult instanceof EntityHitResult firstEntity && entityHit.getEntity().getUuid().compareTo(firstEntity.getEntity().getUuid()) == 0) {
if (client.interactionManager.interactEntity(client.player, entityHit.getEntity(), client.player.getActiveHand()) == ActionResult.SUCCESS) {
client.player.swingHand(Hand.MAIN_HAND);
}
firstHitResult = TouchUtils.getTargettedObject(mouseX, mouseY);
}
}
else {
HitResult result = TouchUtils.getTargettedObject(mouseX, mouseY);
if (result != null && firstHitResult != null) {
if (result instanceof BlockHitResult blockHit && firstHitResult instanceof BlockHitResult firstBlock && !blockHit.getBlockPos().equals(firstBlock.getBlockPos())) {
firstHitResult = null;
} else if (result instanceof EntityHitResult entityHit && firstHitResult instanceof EntityHitResult firstEntity && entityHit.getEntity().getUuid().compareTo(firstEntity.getEntity().getUuid()) != 0) {
firstHitResult = null;
}
}
}
}
public static boolean mouseReleased(double mouseX, double mouseY, int button) {
firstHitResult = null;
if ((client.currentScreen == null || !client.currentScreen.mouseReleased(mouseX, mouseY, button)) && System.currentTimeMillis() - clickStartTime < MidnightControlsConfig.touchBreakDelay) {
assert client.player != null;
assert client.world != null;
assert client.interactionManager != null;
clickStartTime = -1;
if (client.player.getMainHandStack() != null && TouchUtils.hasInWorldUseAction(client.player.getMainHandStack())) {
client.interactionManager.stopUsingItem(client.player);
return true;
}
HitResult result = TouchUtils.getTargettedObject(mouseX, mouseY);
if (result == null) return false;
if (result instanceof BlockHitResult blockHit) {
BlockPos blockPos = blockHit.getBlockPos().offset(blockHit.getSide());
BlockState state = client.world.getBlockState(blockPos);
if (client.world.isAir(blockPos) || state.isReplaceable()) {
ItemStack stackInHand = client.player.getMainHandStack();
int previousStackCount = stackInHand.getCount();
var interaction = client.interactionManager.interactBlock(client.player, client.player.getActiveHand(), blockHit);
if (interaction.isAccepted()) {
if (interaction.shouldSwingHand()) {
client.player.swingHand(client.player.preferredHand);
if (!stackInHand.isEmpty() && (stackInHand.getCount() != previousStackCount || client.interactionManager.hasCreativeInventory())) {
client.gameRenderer.firstPersonRenderer.resetEquipProgress(client.player.preferredHand);
}
}
return true;
}
}
}
if (result instanceof EntityHitResult entityHit) {
client.interactionManager.attackEntity(client.player, entityHit.getEntity());
client.player.swingHand(Hand.MAIN_HAND);
}
}
clickStartTime = -1;
return false;
}
}