Compare commits

...

19 Commits

Author SHA1 Message Date
Martin Prokoph
faf24ced17 feat: improve options screen with tooltips & better reset 2025-10-02 17:24:25 +02:00
Martin Prokoph
d7ea484e71 clean: remove double tap to sprint option
Now configurable in vanilla
2025-10-02 17:23:00 +02:00
Martin Prokoph
e24ecdc78b config: reduce default deadzones 2025-10-02 16:24:15 +02:00
Martin Prokoph
66874b7164 feat: fancy input mode icons 2025-10-02 16:22:47 +02:00
Martin Prokoph
238ea583a2 feat: re-order config class 2025-10-02 16:22:22 +02:00
Martin Prokoph
b3b3eb4d55 feat: switch to new MidnightLib-based screen
What used to be the advanced config screen is now the one-and-only default config screen
2025-10-02 16:21:48 +02:00
Martin Prokoph
c2cab16989 fix: controller mouse click simulation in screens 2025-10-02 00:13:40 +02:00
Martin Prokoph
f2372cf406 release: 1.11.3-alpha.2 2025-10-01 17:07:27 +02:00
Martin Prokoph
ffa1bb5a33 fix: get debug hud toggle working correctly 2025-10-01 17:06:20 +02:00
Martin Prokoph
1d9a4287d7 fix: touchscreen interaction finger outline 2025-10-01 16:55:55 +02:00
Martin Prokoph
b3a170f862 fix: server list moving entries instead of cycling 2025-10-01 16:55:09 +02:00
Martin Prokoph
15e1b08e8f fix: attack key not working properly for mobs 2025-10-01 16:54:24 +02:00
Martin Prokoph
7660f6b0ee release: 1.11.3-alpha.1 2025-10-01 14:14:20 +02:00
Martin Prokoph
5c1657aef2 feat: more mouse cursors 🐁 2025-10-01 14:13:47 +02:00
Martin Prokoph
830ac38b02 fix: button category names 2025-10-01 14:12:12 +02:00
Martin Prokoph
4d85879c87 feat: add more functionality to MidnightLib-based config
- The plan is to slowly phase out ObsidianUI, as it is not updated fast enough
2025-10-01 14:11:47 +02:00
Martin Prokoph
60f5142796 fix: correctly register keybind category
This drastically changed in 1.21.9
2025-09-28 13:51:55 +02:00
Martin Prokoph
b8ee08bf81 feat: support more mouse cursor styles 2025-09-28 13:46:09 +02:00
Martin Prokoph
db7f1daa02 port: The Copper Age (1.21.9) 2025-09-27 23:15:20 +02:00
65 changed files with 777 additions and 322 deletions

View File

@@ -1,6 +1,6 @@
plugins { plugins {
id "architectury-plugin" version "3.4-SNAPSHOT" id "architectury-plugin" version "3.4-SNAPSHOT"
id "dev.architectury.loom" version "1.10-SNAPSHOT" apply false id "dev.architectury.loom" version "1.11-SNAPSHOT" apply false
id "me.shedaniel.unified-publishing" version "0.1.+" apply false id "me.shedaniel.unified-publishing" version "0.1.+" apply false
id 'com.github.johnrengelman.shadow' version '8.1.1' apply false id 'com.github.johnrengelman.shadow' version '8.1.1' apply false
} }

View File

@@ -9,12 +9,20 @@
package eu.midnightdust.midnightcontrols; package eu.midnightdust.midnightcontrols;
import net.minecraft.text.Text;
import net.minecraft.text.object.AtlasTextObjectContents;
import net.minecraft.text.object.TextObjectContents;
import net.minecraft.util.Atlases;
import net.minecraft.util.Identifier;
import net.minecraft.util.TranslatableOption;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.thinkingstudio.obsidianui.util.Nameable; import org.thinkingstudio.obsidianui.util.Nameable;
import java.util.Arrays; import java.util.Arrays;
import java.util.Optional; import java.util.Optional;
import static eu.midnightdust.midnightcontrols.MidnightControls.id;
/** /**
* Represents the controls mode. * Represents the controls mode.
* *
@@ -22,10 +30,15 @@ import java.util.Optional;
* @version 1.7.0 * @version 1.7.0
* @since 1.0.0 * @since 1.0.0
*/ */
public enum ControlsMode { public enum ControlsMode implements TranslatableOption {
DEFAULT, DEFAULT("icon/keyboard_mouse"),
CONTROLLER, CONTROLLER("icon/controller"),
TOUCHSCREEN; TOUCHSCREEN("icon/touchscreen");
final String emoji;
ControlsMode(String emoji) {
this.emoji = emoji;
}
/** /**
* Returns the next controls mode available. * Returns the next controls mode available.
@@ -39,6 +52,16 @@ public enum ControlsMode {
return v[this.ordinal() + 1]; return v[this.ordinal() + 1];
} }
@Override
public int getId() {
return this.ordinal();
}
@Override
public Text getText() {
return Text.object(new AtlasTextObjectContents(Atlases.GUI, id(emoji))).append(" ").append(Text.translatable(getTranslationKey()));
}
/** /**
* Gets the translation key of this controls mode. * Gets the translation key of this controls mode.
* *
@@ -49,6 +72,7 @@ public enum ControlsMode {
return "midnightcontrols.controls_mode." + this.getName(); return "midnightcontrols.controls_mode." + this.getName();
} }
public @NotNull String getName() { public @NotNull String getName() {
return this.name().toLowerCase(); return this.name().toLowerCase();
} }

View File

@@ -56,21 +56,20 @@ import java.util.concurrent.atomic.AtomicReference;
*/ */
public class MidnightControlsClient extends MidnightControls { public class MidnightControlsClient extends MidnightControls {
public static boolean lateInitDone = false; public static boolean lateInitDone = false;
public static final KeyBinding.Category MIDNIGHTCONTROLS_CATEGORY = KeyBinding.Category.create(Identifier.of("midnightcontrols", "keybinds"));
public static final KeyBinding BINDING_LOOK_UP = InputManager.makeKeyBinding(id("look_up"), public static final KeyBinding BINDING_LOOK_UP = InputManager.makeKeyBinding(id("look_up"),
InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_KP_8, "key.categories.midnightcontrols"); InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_KP_8, MIDNIGHTCONTROLS_CATEGORY);
public static final KeyBinding BINDING_LOOK_RIGHT = InputManager.makeKeyBinding(id("look_right"), public static final KeyBinding BINDING_LOOK_RIGHT = InputManager.makeKeyBinding(id("look_right"),
InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_KP_6, "key.categories.midnightcontrols"); InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_KP_6, MIDNIGHTCONTROLS_CATEGORY);
public static final KeyBinding BINDING_LOOK_DOWN = InputManager.makeKeyBinding(id("look_down"), public static final KeyBinding BINDING_LOOK_DOWN = InputManager.makeKeyBinding(id("look_down"),
InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_KP_2, "key.categories.midnightcontrols"); InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_KP_2, MIDNIGHTCONTROLS_CATEGORY);
public static final KeyBinding BINDING_LOOK_LEFT = InputManager.makeKeyBinding(id("look_left"), public static final KeyBinding BINDING_LOOK_LEFT = InputManager.makeKeyBinding(id("look_left"),
InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_KP_4, "key.categories.midnightcontrols"); InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_KP_4, MIDNIGHTCONTROLS_CATEGORY);
public static final KeyBinding BINDING_RING = InputManager.makeKeyBinding(id("ring"), public static final KeyBinding BINDING_RING = InputManager.makeKeyBinding(id("ring"),
InputUtil.Type.KEYSYM, InputUtil.UNKNOWN_KEY.getCode(), "key.categories.midnightcontrols"); InputUtil.Type.KEYSYM, InputUtil.UNKNOWN_KEY.getCode(), MIDNIGHTCONTROLS_CATEGORY);
public static final Identifier CONTROLLER_BUTTONS = id("textures/gui/controller_buttons.png"); public static final Identifier CONTROLLER_BUTTONS = id("textures/gui/controller_buttons.png");
public static final Identifier CONTROLLER_EXPANDED = id("textures/gui/controller_expanded.png"); public static final Identifier CONTROLLER_EXPANDED = id("textures/gui/controller_expanded.png");
public static final Identifier CONTROLLER_AXIS = id("textures/gui/controller_axis.png"); public static final Identifier CONTROLLER_AXIS = id("textures/gui/controller_axis.png");
public static final Identifier WAYLAND_CURSOR_TEXTURE_LIGHT = id("cursor/light/mouse_pointer");
public static final Identifier WAYLAND_CURSOR_TEXTURE_DARK = id("cursor/dark/mouse_pointer");
public static final File MAPPINGS_FILE = new File("config/gamecontrollercustommappings.txt"); public static final File MAPPINGS_FILE = new File("config/gamecontrollercustommappings.txt");
public static MinecraftClient client = MinecraftClient.getInstance(); public static MinecraftClient client = MinecraftClient.getInstance();
public static final MidnightInput input = new MidnightInput(); public static final MidnightInput input = new MidnightInput();
@@ -150,20 +149,20 @@ public class MidnightControlsClient extends MidnightControls {
if (PlatformFunctions.isModLoaded("wynntils") && KeyBindingIDAccessor.getKEYS_BY_ID().entrySet().stream().noneMatch(b -> Objects.equals(b.getValue().getCategory(), "Wynntils"))) return; if (PlatformFunctions.isModLoaded("wynntils") && KeyBindingIDAccessor.getKEYS_BY_ID().entrySet().stream().noneMatch(b -> Objects.equals(b.getValue().getCategory(), "Wynntils"))) return;
for (int i = 0; i < KeyBindingIDAccessor.getKEYS_BY_ID().size(); ++i) { for (int i = 0; i < KeyBindingIDAccessor.getKEYS_BY_ID().size(); ++i) {
KeyBinding keyBinding = KeyBindingIDAccessor.getKEYS_BY_ID().entrySet().stream().toList().get(i).getValue(); KeyBinding keyBinding = KeyBindingIDAccessor.getKEYS_BY_ID().entrySet().stream().toList().get(i).getValue();
if (MidnightControlsConfig.excludedKeybindings.stream().noneMatch(excluded -> keyBinding.getTranslationKey().startsWith(excluded))) { if (MidnightControlsConfig.excludedKeybindings.stream().noneMatch(excluded -> keyBinding.getId().startsWith(excluded))) {
if (!keyBinding.getTranslationKey().contains(MidnightControlsConstants.NAMESPACE)) { if (!keyBinding.getId().contains(MidnightControlsConstants.NAMESPACE)) {
AtomicReference<ButtonCategory> category = new AtomicReference<>(); AtomicReference<ButtonCategory> category = new AtomicReference<>();
InputManager.streamCategories().forEach(buttonCategory -> { InputManager.streamCategories().forEach(buttonCategory -> {
if (buttonCategory.getIdentifier().equals(validVanillaId(keyBinding.getCategory()))) if (buttonCategory.getIdentifier().equals(keyBinding.getCategory().id()))
category.set(buttonCategory); category.set(buttonCategory);
}); });
if (category.get() == null) { if (category.get() == null) {
category.set(new ButtonCategory(validVanillaId(keyBinding.getCategory()))); category.set(new ButtonCategory(keyBinding.getCategory().id()));
InputManager.registerCategory(category.get()); InputManager.registerCategory(category.get());
} }
ButtonBinding buttonBinding = new ButtonBinding.Builder(keyBinding.getTranslationKey()).category(category.get()).linkKeybind(keyBinding).register(); ButtonBinding buttonBinding = new ButtonBinding.Builder(keyBinding.getId()).category(category.get()).linkKeybind(keyBinding).register();
if (MidnightControlsConfig.debug) { if (MidnightControlsConfig.debug) {
MidnightControls.log(keyBinding.getTranslationKey()); MidnightControls.log(keyBinding.getId());
MidnightControls.log(String.valueOf(buttonBinding)); MidnightControls.log(String.valueOf(buttonBinding));
} }
} }
@@ -172,14 +171,6 @@ public class MidnightControlsClient extends MidnightControls {
InputManager.loadButtonBindings(); InputManager.loadButtonBindings();
lateInitDone = true; lateInitDone = true;
} }
private static Identifier validVanillaId(String path) {
for(int i = 0; i < path.length(); ++i) {
if (!Identifier.isPathCharacterValid(path.charAt(i))) {
path = path.replace(path.charAt(i), '_');
}
}
return Identifier.ofVanilla(path);
}
/** /**
* This method is called every Minecraft tick. * This method is called every Minecraft tick.

View File

@@ -12,12 +12,16 @@ package eu.midnightdust.midnightcontrols.client;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.mojang.blaze3d.platform.GLX; import com.mojang.blaze3d.platform.GLX;
import eu.midnightdust.lib.config.EntryInfo;
import eu.midnightdust.lib.config.MidnightConfig; import eu.midnightdust.lib.config.MidnightConfig;
import eu.midnightdust.lib.config.MidnightConfigListWidget;
import eu.midnightdust.lib.config.MidnightConfigScreen;
import eu.midnightdust.midnightcontrols.ControlsMode; import eu.midnightdust.midnightcontrols.ControlsMode;
import eu.midnightdust.midnightcontrols.MidnightControls; import eu.midnightdust.midnightcontrols.MidnightControls;
import eu.midnightdust.midnightcontrols.MidnightControlsConstants; import eu.midnightdust.midnightcontrols.MidnightControlsConstants;
import eu.midnightdust.midnightcontrols.MidnightControlsFeature; import eu.midnightdust.midnightcontrols.MidnightControlsFeature;
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding; import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
import eu.midnightdust.midnightcontrols.client.controller.ButtonCategory;
import eu.midnightdust.midnightcontrols.client.controller.Controller; import eu.midnightdust.midnightcontrols.client.controller.Controller;
import eu.midnightdust.midnightcontrols.client.controller.InputManager; import eu.midnightdust.midnightcontrols.client.controller.InputManager;
import eu.midnightdust.midnightcontrols.client.enums.ButtonState; import eu.midnightdust.midnightcontrols.client.enums.ButtonState;
@@ -27,13 +31,21 @@ import eu.midnightdust.midnightcontrols.client.enums.HudSide;
import eu.midnightdust.midnightcontrols.client.enums.VirtualMouseSkin; import eu.midnightdust.midnightcontrols.client.enums.VirtualMouseSkin;
import eu.midnightdust.midnightcontrols.client.gui.RingScreen; import eu.midnightdust.midnightcontrols.client.gui.RingScreen;
import eu.midnightdust.midnightcontrols.client.enums.TouchMode; import eu.midnightdust.midnightcontrols.client.enums.TouchMode;
import eu.midnightdust.midnightcontrols.client.gui.config.ControllerBindingButton;
import eu.midnightdust.midnightcontrols.client.gui.config.ControllerSelectionButton;
import eu.midnightdust.midnightcontrols.client.virtualkeyboard.KeyboardLayoutManager;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.ChatScreen; import net.minecraft.client.gui.screen.ChatScreen;
import net.minecraft.client.gui.screen.advancement.AdvancementsScreen; import net.minecraft.client.gui.screen.advancement.AdvancementsScreen;
import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.client.gui.widget.TextIconButtonWidget;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
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 java.lang.annotation.Annotation;
import java.util.*; import java.util.*;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@@ -49,22 +61,63 @@ public class MidnightControlsConfig extends MidnightConfig {
public static final String SCREENS = "screens"; public static final String SCREENS = "screens";
public static final String VISUAL = "visual"; public static final String VISUAL = "visual";
public static final String MISC = "misc"; public static final String MISC = "misc";
public static final String BUTTONS = "buttons";
public static boolean isEditing = false; public static boolean isEditing = false;
@Hidden @Entry public static int configVersion = 2; @Hidden @Entry public static int configVersion = 2;
// General
@Comment(category = CONTROLLER, centered = true, name="\uD83C\uDFAE General") public static Comment _general; // Controller
@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;
@Comment(category = CONTROLLER, centered = true, name="\uD83D\uDD90 Input Mode") public static Comment _input_mode;
@Entry(category = CONTROLLER, name = "midnightcontrols.menu.controls_mode") public static ControlsMode controlsMode = ControlsMode.DEFAULT; @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 = CONTROLLER, name = "midnightcontrols.menu.auto_switch_mode") public static boolean autoSwitchMode = true;
// HUD
@Comment(category = CONTROLLER, centered = true, name="\uD83D\uDCF7 Camera Settings") public static Comment _cameraSettings;
@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;
@Comment(category = CONTROLLER, centered = true, name="\uD83D\uDC40 Eye Tracking") public static Comment _eyeTracker;
@Entry(category = CONTROLLER, name = "midnightcontrols.menu.eye_tracker_as_mouse") public static boolean eyeTrackerAsMouse = false;
@Entry(category = CONTROLLER, 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;
@Comment(category = CONTROLLER, centered = true, name="\uD83D\uDD79 Max Analog Stick Values") public static Comment _maxAnalogValues;
@Entry(category = CONTROLLER, name = "Max analog value: Left X", isSlider = true, min = .25f, max = 1.f) public static double maxAnalogValueLeftX = 1;
@Entry(category = CONTROLLER, name = "Max analog value: Left Y", isSlider = true, min = .25f, max = 1.f) public static double maxAnalogValueLeftY = 1;
@Entry(category = CONTROLLER, name = "Max analog value: Right X", isSlider = true, min = .25f, max = 1.f) public static double maxAnalogValueRightX = 1;
@Entry(category = CONTROLLER, name = "Max analog value: Right Y", isSlider = true, min = .25f, max = 1.f) public static double maxAnalogValueRightY = 1;
@Comment(category = CONTROLLER, centered = true, name="☠ Dead Zones") public static Comment _deadZones;
@Entry(category = CONTROLLER, name = "midnightcontrols.menu.right_dead_zone", isSlider = true, min = 0.05, max = 1) public static double rightDeadZone = 0.15;
@Entry(category = CONTROLLER, name = "midnightcontrols.menu.left_dead_zone", isSlider = true, min = 0.05, max = 1) public static double leftDeadZone = 0.15;
@Entry(category = CONTROLLER, name = "Trigger Dead-Zone", isSlider = true, min = 0.05, max = 1) public static double triggerDeadZone = 0.1;
// Init button binding tab (see #onTabInit())
@Comment(category = BUTTONS) @Condition(requiredModId = "thisModDoesNotExist") public static Comment this_spacer_will_never_be_visible;
@Entry @Hidden public static Map<String, String> BINDING = new HashMap<>();
private static final Pattern BUTTON_BINDING_PATTERN = Pattern.compile("(-?\\d+)\\+?");
// Visual
@Comment(category = VISUAL, centered = true, name="\uD83D\uDDB9 Hud") public static Comment _hud; @Comment(category = VISUAL, centered = true, name="\uD83D\uDDB9 Hud") public static Comment _hud;
@Entry(category = VISUAL, name = "midnightcontrols.menu.hud_enable") public static boolean hudEnable = true; @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 = VISUAL, name = "midnightcontrols.menu.hud_side") public static HudSide hudSide = HudSide.LEFT;
@Entry(category = VISUAL, name = "midnightcontrols.menu.controller_type") public static ControllerType controllerType = ControllerType.DEFAULT; @Entry(category = VISUAL, name = "midnightcontrols.menu.controller_type") public static ControllerType controllerType = ControllerType.DEFAULT;
@Comment(category = VISUAL, centered = true, name="⊽ Reacharound") public static Comment _reacharoundOutline;
@Condition(requiredModId = "midnightcontrols-extra")
@Entry(category = VISUAL, name = "Reacharound Outline") public static boolean shouldRenderReacharoundOutline = true;
@Condition(requiredModId = "midnightcontrols-extra", requiredOption = "shouldRenderReacharoundOutline")
@Entry(category = VISUAL, name = "Reacharound Outline Color", isColor = true) public static String reacharoundOutlineColorHex = "#ffffff";
@Condition(requiredModId = "midnightcontrols-extra", requiredOption = "shouldRenderReacharoundOutline")
@Entry(category = VISUAL, name = "Reacharound Outline Alpha", isSlider = true, min = 0, max = 255) public static int reacharoundOutlineColorAlpha = 102;
// Gameplay // Gameplay
@Comment(category = GAMEPLAY, centered = true, name="\uD83D\uDECB Comfort") public static Comment _comfort; @Comment(category = GAMEPLAY, centered = true, name="\uD83D\uDECB Comfort") public static Comment _comfort;
@Entry(category = GAMEPLAY, name = "Enable Hints") public static boolean enableHints = true; @Entry(category = GAMEPLAY, name = "Enable Hints") public static boolean enableHints = true;
@Entry(category = GAMEPLAY, name = "midnightcontrols.menu.analog_movement") public static boolean analogMovement = true; @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_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.controller_toggle_sprint") public static boolean controllerToggleSprint = MinecraftClient.getInstance().options.getSprintToggled().getValue();
@@ -81,19 +134,8 @@ public class MidnightControlsConfig extends MidnightConfig {
@Condition(requiredModId = "midnightcontrols-extra") @Condition(requiredModId = "midnightcontrols-extra")
@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 = GAMEPLAY, name = "midnightcontrols.menu.reacharound.vertical") public static boolean verticalReacharound = false; // Disabled by default as this behaviour can be considered cheating on multiplayer servers.
@Condition(requiredModId = "midnightcontrols-extra") @Condition(requiredModId = "midnightcontrols-extra")
@Comment(category = VISUAL, centered = true, name="⊽ Reacharound") public static Comment _reacharoundOutline;
@Condition(requiredModId = "midnightcontrols-extra") // Screens
@Entry(category = VISUAL, name = "Reacharound Outline") public static boolean shouldRenderReacharoundOutline = true;
@Condition(requiredModId = "midnightcontrols-extra", requiredOption = "shouldRenderReacharoundOutline")
@Entry(category = VISUAL, name = "Reacharound Outline Color", isColor = true) public static String reacharoundOutlineColorHex = "#ffffff";
@Condition(requiredModId = "midnightcontrols-extra", requiredOption = "shouldRenderReacharoundOutline")
@Entry(category = VISUAL, name = "Reacharound Outline Alpha", isSlider = true, min = 0, max = 255) public static int reacharoundOutlineColorAlpha = 102;
@Comment(category = CONTROLLER, centered = true, name="\uD83D\uDCF7 Camera Settings") public static Comment _cameraSettings;
@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;
@Comment(category = SCREENS, centered = true, name="\uD83D\uDDB1 Mouse Behaviour") public static Comment _mouseBehaviour; @Comment(category = SCREENS, centered = true, name="\uD83D\uDDB1 Mouse Behaviour") public static Comment _mouseBehaviour;
@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.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.joystick_as_mouse") public static boolean joystickAsMouse = false;
@@ -103,62 +145,100 @@ public class MidnightControlsConfig extends MidnightConfig {
"me.shedaniel.clothconfig2.gui.ClothConfigScreen", "com.mamiyaotaru.voxelmap.gui.GuiWaypoints", "com.mamiyaotaru.voxelmap.gui.GuiPersistentMap"); "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 = "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 = SCREENS, name = "WASD screens") public static List<String> wasdScreens = Lists.newArrayList("com.ultreon.devices.core.Laptop");
@Comment(category = CONTROLLER, centered = true, name="\uD83D\uDC40 Eye Tracking") public static Comment _eyeTracker;
@Entry(category = CONTROLLER, name = "midnightcontrols.menu.eye_tracker_as_mouse") public static boolean eyeTrackerAsMouse = false;
@Entry(category = CONTROLLER, 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;
@Comment(category = SCREENS, centered = true, name="\uD83D\uDC46 Virtual Mouse") public static Comment _virtualMouse; @Comment(category = SCREENS, centered = true, name="\uD83D\uDC46 Virtual Mouse") public static Comment _virtualMouse;
@Entry(category = SCREENS, name = "midnightcontrols.menu.virtual_mouse") public static boolean virtualMouse = false; @Entry(category = SCREENS, name = "midnightcontrols.menu.virtual_mouse") public static boolean virtualMouse = false;
@Condition(requiredOption = "virtualMouse", visibleButLocked = true) @Condition(requiredOption = "virtualMouse", visibleButLocked = true)
@Entry(category = SCREENS, name = "midnightcontrols.menu.virtual_mouse.skin") public static VirtualMouseSkin virtualMouseSkin = VirtualMouseSkin.DEFAULT_LIGHT; @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 = SCREENS, name = "midnightcontrols.menu.hide_cursor") public static boolean hideNormalMouse = false;
@Entry(category = SCREENS, name = "midnightcontrols.menu.virtual_keyboard") public static boolean virtualKeyboard = false; @Entry(category = SCREENS, name = "midnightcontrols.menu.virtual_keyboard") public static boolean virtualKeyboard = 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; @Comment(category = SCREENS, centered = true, name="\uD83D\uDD27 UI Modifications") public static Comment _uiMods;
@Entry(category = SCREENS, name = "midnightcontrols.menu.move_chat") public static boolean moveChat = false;
@Entry(category = SCREENS, name = "Enable Shortcut in Controls Options") public static boolean shortcutInControls = true;
// Touch
@Comment(category = TOUCH, centered = true, name="\uD83E\uDE84 Behaviour") public static Comment _touchBehaviour; @Comment(category = TOUCH, centered = true, name="\uD83E\uDE84 Behaviour") public static Comment _touchBehaviour;
@Entry(category = TOUCH, name = "midnightcontrols.menu.touch_with_controller") public static boolean touchInControllerMode = false; @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.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.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_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_break_delay", isSlider = true, min = 50, max = 500) public static int touchBreakDelay = 120;
@Comment(category = TOUCH, centered = true, name="\uD83D\uDCA1 Visuals") public static Comment _visuals; @Comment(category = TOUCH, centered = true, name="\uD83D\uDCA1 Visuals") public static Comment _visuals;
@Entry(category = TOUCH, name = "midnightcontrols.menu.touch_transparency", isSlider = true, min = 0, max = 100) public static int touchTransparency = 75; @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 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 = "Touch Outline Alpha", isSlider = true, min = 0, max = 255) public static int touchOutlineColorAlpha = 150;
@Comment(category = TOUCH, centered = true, name="\uD83E\uDDEA Advanced") public static Comment _advanced; @Comment(category = TOUCH, centered = true, name="\uD83E\uDDEA Advanced") public static Comment _advanced;
@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 = "Screens with close button") public static List<String> closeButtonScreens = Lists.newArrayList(ChatScreen.class.getCanonicalName(), AdvancementsScreen.class.getCanonicalName(), RingScreen.class.getCanonicalName());
@Entry(category = TOUCH, name = "Left Touch button bindings") public static List<String> leftTouchBinds = Lists.newArrayList("debug_screen", "screenshot","toggle_perspective"); @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 = 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<>(); // Miscellaneous
@Entry(category = MISC) @Hidden public static String keyboardLayout = "en_US:qwerty";
private static final Pattern BUTTON_BINDING_PATTERN = Pattern.compile("(-?\\d+)\\+?");
@Comment(category = CONTROLLER, centered = true, name="\uD83D\uDD79 Max Analog Stick Values") public static Comment _maxAnalogValues;
@Entry(category = CONTROLLER, name = "Max analog value: Left X", isSlider = true, min = .25f, max = 1.f) public static double maxAnalogValueLeftX = 1;
@Entry(category = CONTROLLER, name = "Max analog value: Left Y", isSlider = true, min = .25f, max = 1.f) public static double maxAnalogValueLeftY = 1;
@Entry(category = CONTROLLER, name = "Max analog value: Right X", isSlider = true, min = .25f, max = 1.f) public static double maxAnalogValueRightX = 1;
@Entry(category = CONTROLLER, name = "Max analog value: Right Y", isSlider = true, min = .25f, max = 1.f) public static double maxAnalogValueRightY = 1;
@Comment(category = CONTROLLER, centered = true, name="☠ Dead Zones") public static Comment _deadZones;
@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 = "Trigger Dead-Zone", isSlider = true, min = 0.05, max = 1) public static double triggerDeadZone = 0.1;
@Comment(category = CONTROLLER, centered = true, name="☆ Other Options") public static Comment _otherOptions;
@Entry(category = CONTROLLER, name = "Trigger button fix") public static boolean triggerFix = true;
@Entry(category = CONTROLLER, name = "Excluded Controllers (Name Regex)") public static List<String> excludedControllers = Lists.newArrayList(".*(Keyboard)$", ".*(Touchpad)$", ".*(Pen)$", ".*(Finger)$");
@Comment(category = SCREENS, centered = true, name="\uD83D\uDD27 UI Modifications") public static Comment _uiMods;
@Entry(category = SCREENS, name = "midnightcontrols.menu.move_chat") public static boolean moveChat = false;
@Entry(category = SCREENS, name = "Enable Shortcut in Controls Options") public static boolean shortcutInControls = true;
@Entry(category = MISC, name = "midnightcontrols.menu.virtual_keyboard_layout") public static String keyboardLayout = "en_US:qwerty";
@Entry(category = MISC, name = "Debug") public static boolean debug = false; @Entry(category = MISC, name = "Debug") public static boolean debug = false;
@Entry(category = MISC, 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 = MISC, 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.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"); "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 = MISC, name = "Ring Bindings (WIP)") @Hidden public static List<String> ringBindings = new ArrayList<>(); @Entry(category = MISC, name = "Ring Bindings (WIP)") @Hidden 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 = MISC, name = "Ignored Unbound Keys") public static List<String> ignoredUnboundKeys = Lists.newArrayList("inventorytabs.key.next_tab");
@Comment(category = MISC, centered = true, name="☆ Other Options") public static Comment _otherOptions;
@Entry(category = MISC, name = "Trigger button fix") public static boolean triggerFix = true;
@Entry(category = MISC, name = "Excluded Controllers (Name Regex)") public static List<String> excludedControllers = Lists.newArrayList(".*(Keyboard)$", ".*(Touchpad)$", ".*(Pen)$", ".*(Finger)$");
@Entry @Hidden public static Map<String, Map<String, String>> controllerBindingProfiles = new HashMap<>(); @Entry @Hidden public static Map<String, Map<String, String>> controllerBindingProfiles = new HashMap<>();
private static Map<String, String> currentBindingProfile = new HashMap<>(); private static Map<String, String> currentBindingProfile = new HashMap<>();
private static Controller prevController; private static Controller prevController;
public void onTabInit(String tabName, MidnightConfigListWidget list, MidnightConfigScreen screen) {
EntryInfo centeredComment = new EntryInfo(null, "midnightcontrols");
centeredComment.comment = new Comment() {
public Class<? extends Annotation> annotationType() {return null;}
public String category() {return "";}
public String name() {return "";}
public String url() {return "";}
public String requiredMod() {return "";}
@Override
public boolean centered() {
return true;
}
};
if (BUTTONS.equals(tabName)) {
InputManager.streamCategories()
.sorted(Comparator.comparingInt(ButtonCategory::getPriority))
.forEach(category -> {
list.addButton(Lists.newArrayList(), Text.literal(category.getTranslatedName()), centeredComment);
category.getBindings().forEach(binding -> {
ControllerBindingButton.add(binding, list, screen);
});
});
}
if (MISC.equals(tabName)) {
TextIconButtonWidget resetButton = TextIconButtonWidget.builder(Text.translatable("controls.reset"), (button -> {
MidnightControlsConfig.keyboardLayout = "en_US:qwerty";
screen.updateList();
}), true).texture(Identifier.of("midnightlib","icon/reset"), 12, 12).dimension(20, 20).build();
resetButton.setPosition(screen.width - 205 + 150 + 25, 0);
ButtonWidget editButton = ButtonWidget.builder(Text.translatable(KeyboardLayoutManager.getById(MidnightControlsConfig.keyboardLayout).getTranslationKey()),
button -> {
MidnightControlsConfig.keyboardLayout = KeyboardLayoutManager.getNext(KeyboardLayoutManager.getById(MidnightControlsConfig.keyboardLayout)).getId();
resetButton.active = !MidnightControlsConfig.keyboardLayout.equals("en_US:qwerty");
button.setMessage(Text.translatable(KeyboardLayoutManager.getById(MidnightControlsConfig.keyboardLayout).getTranslationKey()));
}).dimensions(screen.width - 185, 0, 150, 20).build();
resetButton.active = !MidnightControlsConfig.keyboardLayout.equals("en_US:qwerty");
list.addButton(List.of(editButton, resetButton), Text.translatable("midnightcontrols.menu.virtual_keyboard_layout"), new EntryInfo(null, screen.modid));
}
if (CONTROLLER.equals(tabName)) {
list.addButton(List.of(), Text.of("\uD83C\uDFAE General"), centeredComment);
ControllerSelectionButton.add(list, screen, false);
ControllerSelectionButton.add(list, screen, true);
}
}
/** /**
* Loads the configuration * Loads the configuration
*/ */
@@ -383,7 +463,6 @@ public class MidnightControlsConfig extends MidnightConfig {
hudEnable = true; hudEnable = true;
hudSide = HudSide.LEFT; hudSide = HudSide.LEFT;
analogMovement = true; analogMovement = true;
doubleTapToSprint = true;
controllerToggleSneak = MinecraftClient.getInstance().options.getSneakToggled().getValue(); controllerToggleSneak = MinecraftClient.getInstance().options.getSneakToggled().getValue();
controllerToggleSprint = MinecraftClient.getInstance().options.getSprintToggled().getValue(); controllerToggleSprint = MinecraftClient.getInstance().options.getSprintToggled().getValue();
fastBlockPlacing = false; fastBlockPlacing = false;

View File

@@ -21,8 +21,8 @@ import eu.midnightdust.midnightcontrols.client.gui.MidnightControlsSettingsScree
* @since 1.1.0 * @since 1.1.0
*/ */
public class MidnightControlsModMenu implements ModMenuApi { public class MidnightControlsModMenu implements ModMenuApi {
@Override // @Override
public ConfigScreenFactory<?> getModConfigScreenFactory() { // public ConfigScreenFactory<?> getModConfigScreenFactory() {
return parent -> new MidnightControlsSettingsScreen(parent, false); // return parent -> new MidnightControlsSettingsScreen(parent, false);
} // }
} }

View File

@@ -15,16 +15,21 @@ import eu.midnightdust.midnightcontrols.client.compat.EmotecraftCompat;
import eu.midnightdust.midnightcontrols.client.compat.LibGuiCompat; import eu.midnightdust.midnightcontrols.client.compat.LibGuiCompat;
import eu.midnightdust.midnightcontrols.client.compat.MidnightControlsCompat; import eu.midnightdust.midnightcontrols.client.compat.MidnightControlsCompat;
import eu.midnightdust.midnightcontrols.client.compat.YACLCompat; import eu.midnightdust.midnightcontrols.client.compat.YACLCompat;
import eu.midnightdust.midnightcontrols.client.gui.config.ControlsInput;
import eu.midnightdust.midnightcontrols.client.mixin.AdvancementsScreenAccessor; import eu.midnightdust.midnightcontrols.client.mixin.AdvancementsScreenAccessor;
import eu.midnightdust.midnightcontrols.client.mixin.CreativeInventoryScreenAccessor; import eu.midnightdust.midnightcontrols.client.mixin.CreativeInventoryScreenAccessor;
import eu.midnightdust.midnightcontrols.client.mixin.KeyboardAccessor;
import eu.midnightdust.midnightcontrols.client.mixin.MouseAccessor; import eu.midnightdust.midnightcontrols.client.mixin.MouseAccessor;
import eu.midnightdust.midnightcontrols.client.util.InventoryUtil; import eu.midnightdust.midnightcontrols.client.util.InventoryUtil;
import eu.midnightdust.midnightcontrols.client.util.storage.AxisStorage; import eu.midnightdust.midnightcontrols.client.util.storage.AxisStorage;
import eu.midnightdust.midnightcontrols.client.util.storage.ButtonStorage; import eu.midnightdust.midnightcontrols.client.util.storage.ButtonStorage;
import net.minecraft.client.gui.Click;
import net.minecraft.client.gui.screen.option.KeybindsScreen; import net.minecraft.client.gui.screen.option.KeybindsScreen;
import net.minecraft.client.gui.widget.EntryListWidget; import net.minecraft.client.gui.widget.EntryListWidget;
import net.minecraft.client.gui.widget.PressableWidget; import net.minecraft.client.gui.widget.PressableWidget;
import net.minecraft.client.gui.widget.SliderWidget; import net.minecraft.client.gui.widget.SliderWidget;
import net.minecraft.client.input.KeyInput;
import net.minecraft.client.input.MouseInput;
import net.minecraft.entity.vehicle.BoatEntity; import net.minecraft.entity.vehicle.BoatEntity;
import org.thinkingstudio.obsidianui.widget.AbstractSpruceWidget; import org.thinkingstudio.obsidianui.widget.AbstractSpruceWidget;
import org.thinkingstudio.obsidianui.widget.container.SpruceEntryListWidget; import org.thinkingstudio.obsidianui.widget.container.SpruceEntryListWidget;
@@ -35,7 +40,6 @@ import eu.midnightdust.midnightcontrols.client.controller.InputManager;
import eu.midnightdust.midnightcontrols.client.enums.CameraMode; import eu.midnightdust.midnightcontrols.client.enums.CameraMode;
import eu.midnightdust.midnightcontrols.client.gui.RingScreen; import eu.midnightdust.midnightcontrols.client.gui.RingScreen;
import eu.midnightdust.midnightcontrols.client.touch.gui.TouchscreenOverlay; import eu.midnightdust.midnightcontrols.client.touch.gui.TouchscreenOverlay;
import eu.midnightdust.midnightcontrols.client.gui.widget.ControllerControlsWidget;
import eu.midnightdust.midnightcontrols.client.ring.RingPage; import eu.midnightdust.midnightcontrols.client.ring.RingPage;
import eu.midnightdust.midnightcontrols.client.util.HandledScreenAccessor; import eu.midnightdust.midnightcontrols.client.util.HandledScreenAccessor;
import eu.midnightdust.midnightcontrols.client.util.MathUtil; import eu.midnightdust.midnightcontrols.client.util.MathUtil;
@@ -54,9 +58,6 @@ import net.minecraft.client.gui.screen.advancement.AdvancementTab;
import net.minecraft.client.gui.screen.advancement.AdvancementsScreen; import net.minecraft.client.gui.screen.advancement.AdvancementsScreen;
import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen; import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen;
import net.minecraft.client.gui.screen.ingame.HandledScreen; import net.minecraft.client.gui.screen.ingame.HandledScreen;
import net.minecraft.client.gui.screen.ingame.MerchantScreen;
import net.minecraft.client.gui.screen.ingame.StonecutterScreen;
import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen;
import net.minecraft.client.gui.screen.multiplayer.MultiplayerServerListWidget; import net.minecraft.client.gui.screen.multiplayer.MultiplayerServerListWidget;
import net.minecraft.client.gui.screen.world.WorldListWidget; import net.minecraft.client.gui.screen.world.WorldListWidget;
import net.minecraft.text.TranslatableTextContent; import net.minecraft.text.TranslatableTextContent;
@@ -82,6 +83,7 @@ import static org.lwjgl.glfw.GLFW.*;
*/ */
public class MidnightInput { public class MidnightInput {
public static final Map<Integer, Integer> BUTTON_COOLDOWNS = new HashMap<>(); public static final Map<Integer, Integer> BUTTON_COOLDOWNS = new HashMap<>();
public static final KeyInput ENTER_KEY_INPUT = new KeyInput(GLFW_KEY_ENTER, 0, 0);
// Cooldowns // Cooldowns
public int actionGuiCooldown = 0; public int actionGuiCooldown = 0;
public int joystickCooldown = 0; public int joystickCooldown = 0;
@@ -96,7 +98,7 @@ public class MidnightInput {
public int inventoryInteractionCooldown = 0; public int inventoryInteractionCooldown = 0;
public int screenCloseCooldown = 0; public int screenCloseCooldown = 0;
private ControllerControlsWidget controlsInput = null; private ControlsInput controlsInput = null;
public MidnightInput() {} public MidnightInput() {}
@@ -154,7 +156,7 @@ public class MidnightInput {
this.fetchJoystickInput(state, true, false); this.fetchJoystickInput(state, true, false);
}); });
boolean allowInput = this.controlsInput == null || this.controlsInput.focusedBinding == null; boolean allowInput = this.controlsInput == null || this.controlsInput.getFocusedBinding() == null;
if (allowInput) if (allowInput)
InputManager.updateBindings(); InputManager.updateBindings();
@@ -165,11 +167,11 @@ public class MidnightInput {
}); });
} }
if (this.controlsInput != null && InputManager.STATES.int2ObjectEntrySet().parallelStream().map(Map.Entry::getValue).allMatch(ButtonState::isUnpressed)) { if (this.controlsInput != null && InputManager.STATES.int2ObjectEntrySet().parallelStream().map(Map.Entry::getValue).allMatch(ButtonState::isUnpressed)) {
if (MidnightControlsConfig.debug) MidnightControls.log("Starting MidnightInput Button Edit"); //if (MidnightControlsConfig.debug) MidnightControls.log("Starting MidnightInput Button Edit");
if (this.controlsInput.focusedBinding != null && !this.controlsInput.waiting) { if (this.controlsInput.getFocusedBinding() != null && !this.controlsInput.isWaiting()) {
int[] buttons = new int[this.controlsInput.currentButtons.size()]; int[] buttons = new int[this.controlsInput.getCurrentButtons().size()];
for (int i = 0; i < this.controlsInput.currentButtons.size(); i++) for (int i = 0; i < this.controlsInput.getCurrentButtons().size(); i++)
buttons[i] = this.controlsInput.currentButtons.get(i); buttons[i] = this.controlsInput.getCurrentButtons().get(i);
this.controlsInput.finishBindingEdit(buttons); this.controlsInput.finishBindingEdit(buttons);
this.controlsInput = null; this.controlsInput = null;
} }
@@ -244,11 +246,11 @@ public class MidnightInput {
this.inventoryInteractionCooldown = 5; this.inventoryInteractionCooldown = 5;
} }
public void beginControlsInput(ControllerControlsWidget widget) { public void beginControlsInput(ControlsInput widget) {
this.controlsInput = widget; this.controlsInput = widget;
if (widget != null) { if (widget != null) {
this.controlsInput.currentButtons.clear(); this.controlsInput.getCurrentButtons().clear();
this.controlsInput.waiting = true; this.controlsInput.setWaiting(true);
} }
} }
@@ -330,16 +332,17 @@ public class MidnightInput {
} }
public void handleButton(ButtonStorage storage) { public void handleButton(ButtonStorage storage) {
if (this.controlsInput != null && this.controlsInput.focusedBinding != null) { if (this.controlsInput != null && this.controlsInput.getFocusedBinding() != null) {
if (storage.state == ButtonState.PRESS && !this.controlsInput.currentButtons.contains(storage.button)) { if (storage.state == ButtonState.PRESS && !this.controlsInput.getCurrentButtons().contains(storage.button)) {
this.controlsInput.currentButtons.add(storage.button); this.controlsInput.getCurrentButtons().add(storage.button);
var buttons = new int[this.controlsInput.currentButtons.size()]; var buttons = new int[this.controlsInput.getCurrentButtons().size()];
for (int i = 0; i < this.controlsInput.currentButtons.size(); i++) for (int i = 0; i < this.controlsInput.getCurrentButtons().size(); i++)
buttons[i] = this.controlsInput.currentButtons.get(i); buttons[i] = this.controlsInput.getCurrentButtons().get(i);
this.controlsInput.focusedBinding.setButton(buttons); this.controlsInput.getFocusedBinding().setButton(buttons);
this.controlsInput.update();
this.controlsInput.waiting = false; this.controlsInput.setWaiting(false);
} }
return; return;
} }
@@ -393,9 +396,9 @@ public class MidnightInput {
accessor.midnightcontrols$onCursorPos(client.getWindow().getHandle(), client.mouse.getX(), client.mouse.getY()); accessor.midnightcontrols$onCursorPos(client.getWindow().getHandle(), client.mouse.getX(), client.mouse.getY());
switch (storage.state) { switch (storage.state) {
// Button pressed // Button pressed
case PRESS -> accessor.midnightcontrols$onMouseButton(client.getWindow().getHandle(), GLFW_MOUSE_BUTTON_LEFT, 1, 0); case PRESS -> accessor.midnightcontrols$onMouseButton(client.getWindow().getHandle(), new MouseInput(GLFW_MOUSE_BUTTON_LEFT, 0), 1);
case RELEASE -> { // Button released case RELEASE -> { // Button released
accessor.midnightcontrols$onMouseButton(client.getWindow().getHandle(), GLFW_MOUSE_BUTTON_LEFT, 0, 0); accessor.midnightcontrols$onMouseButton(client.getWindow().getHandle(), new MouseInput(GLFW_MOUSE_BUTTON_LEFT, 0), 0);
client.currentScreen.setDragging(false); client.currentScreen.setDragging(false);
} }
case REPEAT -> client.currentScreen.setDragging(true); // Button held down / dragging case REPEAT -> client.currentScreen.setDragging(true); // Button held down / dragging
@@ -412,8 +415,8 @@ public class MidnightInput {
if (client.currentScreen instanceof HandledScreen<?> handledScreen && ((HandledScreenAccessor) handledScreen).midnightcontrols$getSlotAt( if (client.currentScreen instanceof HandledScreen<?> handledScreen && ((HandledScreenAccessor) handledScreen).midnightcontrols$getSlotAt(
mouseX, mouseY) != null) return; mouseX, mouseY) != null) return;
if (!this.ignoreNextXRelease && client.currentScreen != null) { if (!this.ignoreNextXRelease && client.currentScreen != null) {
if (storage.state == ButtonState.PRESS) client.currentScreen.mouseClicked(mouseX, mouseY, GLFW.GLFW_MOUSE_BUTTON_2); if (storage.state == ButtonState.PRESS) client.currentScreen.mouseClicked(new Click(mouseX, mouseY, new MouseInput(GLFW.GLFW_MOUSE_BUTTON_2, 1)), false);
else if (storage.state == ButtonState.RELEASE) client.currentScreen.mouseReleased(mouseX, mouseY, GLFW.GLFW_MOUSE_BUTTON_2); else if (storage.state == ButtonState.RELEASE) client.currentScreen.mouseReleased(new Click(mouseX, mouseY, new MouseInput(GLFW.GLFW_MOUSE_BUTTON_2, 0)));
this.screenCloseCooldown = 5; this.screenCloseCooldown = 5;
} else { } else {
this.ignoreNextXRelease = false; this.ignoreNextXRelease = false;
@@ -515,17 +518,18 @@ public class MidnightInput {
// @TODO allow rebinding to left stick // @TODO allow rebinding to left stick
int preferredAxis = true ? GLFW_GAMEPAD_AXIS_RIGHT_Y : GLFW_GAMEPAD_AXIS_LEFT_Y; int preferredAxis = true ? GLFW_GAMEPAD_AXIS_RIGHT_Y : GLFW_GAMEPAD_AXIS_LEFT_Y;
if (this.controlsInput != null && this.controlsInput.focusedBinding != null) { if (this.controlsInput != null && this.controlsInput.getFocusedBinding() != null) {
if (storage.buttonState != ButtonState.NONE && !this.controlsInput.currentButtons.contains(storage.getButtonId(storage.buttonState == ButtonState.PRESS))) { if (storage.buttonState != ButtonState.NONE && !this.controlsInput.getCurrentButtons().contains(storage.getButtonId(storage.buttonState == ButtonState.PRESS))) {
this.controlsInput.currentButtons.add(storage.getButtonId(storage.buttonState == ButtonState.PRESS)); this.controlsInput.getCurrentButtons().add(storage.getButtonId(storage.buttonState == ButtonState.PRESS));
int[] buttons = new int[this.controlsInput.currentButtons.size()]; int[] buttons = new int[this.controlsInput.getCurrentButtons().size()];
for (int i = 0; i < this.controlsInput.currentButtons.size(); i++) for (int i = 0; i < this.controlsInput.getCurrentButtons().size(); i++)
buttons[i] = this.controlsInput.currentButtons.get(i); buttons[i] = this.controlsInput.getCurrentButtons().get(i);
this.controlsInput.focusedBinding.setButton(buttons); this.controlsInput.getFocusedBinding().setButton(buttons);
this.controlsInput.update();
this.controlsInput.waiting = false; this.controlsInput.setWaiting(false);
} }
return true; return true;
} else if (storage.absValue >= storage.deadZone) { } else if (storage.absValue >= storage.deadZone) {
@@ -607,7 +611,7 @@ public class MidnightInput {
public boolean handleAButton(@NotNull Screen screen, @NotNull Element focused) { public boolean handleAButton(@NotNull Screen screen, @NotNull Element focused) {
if (focused instanceof PressableWidget widget) { if (focused instanceof PressableWidget widget) {
widget.playDownSound(MinecraftClient.getInstance().getSoundManager()); widget.playDownSound(MinecraftClient.getInstance().getSoundManager());
widget.onPress(); widget.onPress(ENTER_KEY_INPUT);
return true; return true;
} else if (focused instanceof AbstractSprucePressableButtonWidget widget) { } else if (focused instanceof AbstractSprucePressableButtonWidget widget) {
widget.playDownSound(); widget.playDownSound();
@@ -622,8 +626,8 @@ public class MidnightInput {
} else if (focused instanceof MultiplayerServerListWidget list) { } else if (focused instanceof MultiplayerServerListWidget list) {
var entry = list.getSelectedOrNull(); var entry = list.getSelectedOrNull();
if (entry instanceof MultiplayerServerListWidget.LanServerEntry || entry instanceof MultiplayerServerListWidget.ServerEntry) { if (entry instanceof MultiplayerServerListWidget.LanServerEntry || entry instanceof MultiplayerServerListWidget.ServerEntry) {
((MultiplayerScreen) screen).select(entry); //((MultiplayerScreen) screen).select(entry);
((MultiplayerScreen) screen).connect(); entry.connect();
} }
} else if (focused instanceof SpruceParentWidget) { } else if (focused instanceof SpruceParentWidget) {
var childFocused = ((SpruceParentWidget<?>) focused).getFocused(); var childFocused = ((SpruceParentWidget<?>) focused).getFocused();
@@ -672,7 +676,7 @@ public class MidnightInput {
} }
case SliderWidget slider -> { case SliderWidget slider -> {
if (slider.active) { if (slider.active) {
slider.keyPressed(right ? 262 : 263, 0, 0); slider.keyPressed(new KeyInput(right ? 262 : 263, 0, 0));
this.actionGuiCooldown = 2; // Prevent to press too quickly the focused element, so we have to skip 5 ticks. this.actionGuiCooldown = 2; // Prevent to press too quickly the focused element, so we have to skip 5 ticks.
return true; return true;
} }
@@ -796,7 +800,7 @@ public class MidnightInput {
.anyMatch(element -> { .anyMatch(element -> {
if (element.getMessage().getContent() instanceof TranslatableTextContent translatableText) { if (element.getMessage().getContent() instanceof TranslatableTextContent translatableText) {
if (set.stream().anyMatch(key -> translatableText.getKey().equals(key))) { if (set.stream().anyMatch(key -> translatableText.getKey().equals(key))) {
element.onPress(); element.onPress(ENTER_KEY_INPUT);
return true; return true;
} }
} }
@@ -811,9 +815,9 @@ public class MidnightInput {
} }
public void pressKeyboardKey(MinecraftClient client, int key) { public void pressKeyboardKey(MinecraftClient client, int key) {
client.keyboard.onKey(client.getWindow().getHandle(), key, 0, 1, 0); ((KeyboardAccessor) client.keyboard).midnightcontrols$onKey(client.getWindow().getHandle(), 1, new KeyInput(key, 0, 0));
} }
public void pressKeyboardKey(Screen screen, int key) { public void pressKeyboardKey(Screen screen, int key) {
screen.keyPressed(key, 0, 1); screen.keyPressed(new KeyInput(key, 0, 0));
} }
} }

View File

@@ -125,7 +125,7 @@ public class MidnightReacharound {
if (client.player.isRiding()) if (client.player.isRiding())
return null; return null;
// Temporary pos, do not use // Temporary pos, do not use
Vec3d playerPosi = client.player.getPos(); Vec3d playerPosi = client.player.getEntityPos();
// Imitates var playerPos = client.player.getBlockPos().down(); // Imitates var playerPos = client.player.getBlockPos().down();
Vec3d playerPos = new Vec3d(playerPosi.getX(), playerPosi.getY() - 1.0, playerPosi.getZ()); Vec3d playerPos = new Vec3d(playerPosi.getX(), playerPosi.getY() - 1.0, playerPosi.getZ());

View File

@@ -4,6 +4,7 @@ import dev.emi.emi.api.EmiApi;
import dev.emi.emi.config.EmiConfig; import dev.emi.emi.config.EmiConfig;
import dev.emi.emi.screen.EmiScreenManager; import dev.emi.emi.screen.EmiScreenManager;
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient; import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
import eu.midnightdust.midnightcontrols.client.MidnightInput;
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding; import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
import eu.midnightdust.midnightcontrols.client.controller.ButtonCategory; import eu.midnightdust.midnightcontrols.client.controller.ButtonCategory;
import eu.midnightdust.midnightcontrols.client.controller.InputManager; import eu.midnightdust.midnightcontrols.client.controller.InputManager;
@@ -14,8 +15,8 @@ import static eu.midnightdust.midnightcontrols.MidnightControls.id;
public class EMICompat implements CompatHandler { public class EMICompat implements CompatHandler {
public static boolean handleEmiPages(boolean direction) { public static boolean handleEmiPages(boolean direction) {
if (isEMIEnabled() && MidnightControlsClient.input.actionGuiCooldown == 0 && EmiScreenManager.getSearchPanel() != null && EmiScreenManager.getSearchPanel().pageLeft != null && EmiScreenManager.getSearchPanel().pageRight != null) { if (isEMIEnabled() && MidnightControlsClient.input.actionGuiCooldown == 0 && EmiScreenManager.getSearchPanel() != null && EmiScreenManager.getSearchPanel().pageLeft != null && EmiScreenManager.getSearchPanel().pageRight != null) {
if (direction) EmiScreenManager.getSearchPanel().pageRight.onPress(); if (direction) EmiScreenManager.getSearchPanel().pageRight.onPress(MidnightInput.ENTER_KEY_INPUT);
else EmiScreenManager.getSearchPanel().pageLeft.onPress(); else EmiScreenManager.getSearchPanel().pageLeft.onPress(MidnightInput.ENTER_KEY_INPUT);
MidnightControlsClient.input.actionGuiCooldown = 5; MidnightControlsClient.input.actionGuiCooldown = 5;
return true; return true;
} }

View File

@@ -5,6 +5,7 @@ import eu.midnightdust.midnightcontrols.client.mixin.MouseAccessor;
import io.github.kosmx.emotes.arch.screen.ingame.FastMenuScreen; import io.github.kosmx.emotes.arch.screen.ingame.FastMenuScreen;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.input.MouseInput;
import org.joml.Vector2i; import org.joml.Vector2i;
import org.lwjgl.glfw.GLFW; import org.lwjgl.glfw.GLFW;
@@ -28,7 +29,7 @@ public class EmotecraftCompat {
InputManager.INPUT_MANAGER.updateMousePosition(client); InputManager.INPUT_MANAGER.updateMousePosition(client);
if (stickReleased) { if (stickReleased) {
((MouseAccessor) client.mouse).midnightcontrols$onMouseButton(client.getWindow().getHandle(), GLFW.GLFW_MOUSE_BUTTON_LEFT, GLFW.GLFW_PRESS, 0); ((MouseAccessor) client.mouse).midnightcontrols$onMouseButton(client.getWindow().getHandle(), new MouseInput(GLFW.GLFW_MOUSE_BUTTON_LEFT, 0), GLFW.GLFW_PRESS);
prevIndex = -1; prevIndex = -1;
} }
else prevIndex = index; else prevIndex = index;

View File

@@ -5,6 +5,7 @@ import dev.isxander.yacl.gui.OptionListWidget;
import dev.isxander.yacl.gui.YACLScreen; import dev.isxander.yacl.gui.YACLScreen;
import dev.isxander.yacl.gui.controllers.ControllerWidget; import dev.isxander.yacl.gui.controllers.ControllerWidget;
import dev.isxander.yacl.gui.controllers.slider.SliderControllerElement; import dev.isxander.yacl.gui.controllers.slider.SliderControllerElement;
import eu.midnightdust.midnightcontrols.client.MidnightInput;
import net.minecraft.client.gui.Element; import net.minecraft.client.gui.Element;
import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.Screen;
import org.lwjgl.glfw.GLFW; import org.lwjgl.glfw.GLFW;
@@ -13,7 +14,7 @@ public class YACLCompat implements CompatHandler {
public static boolean handleAButton(Screen screen, Element element) { public static boolean handleAButton(Screen screen, Element element) {
if (element instanceof AbstractWidget abstractWidget) { if (element instanceof AbstractWidget abstractWidget) {
// imitate enter key press // imitate enter key press
return abstractWidget.keyPressed(GLFW.GLFW_KEY_ENTER, 0, 0); return abstractWidget.keyPressed(MidnightInput.ENTER_KEY_INPUT);
} }
return false; return false;
} }

View File

@@ -77,7 +77,7 @@ public class ButtonBinding {
public static final ButtonBinding SCREENSHOT = new Builder("screenshot").buttons(GLFW_GAMEPAD_BUTTON_DPAD_UP, GLFW_GAMEPAD_BUTTON_A) public static final ButtonBinding SCREENSHOT = new Builder("screenshot").buttons(GLFW_GAMEPAD_BUTTON_DPAD_UP, GLFW_GAMEPAD_BUTTON_A)
.action(InputHandlers::handleScreenshot).cooldown().register(); .action(InputHandlers::handleScreenshot).cooldown().register();
public static final ButtonBinding DEBUG_SCREEN = new Builder("debug_screen").buttons(GLFW_GAMEPAD_BUTTON_DPAD_UP, GLFW_GAMEPAD_BUTTON_B) public static final ButtonBinding DEBUG_SCREEN = new Builder("debug_screen").buttons(GLFW_GAMEPAD_BUTTON_DPAD_UP, GLFW_GAMEPAD_BUTTON_B)
.action((client,binding,value,action) -> {if (action == ButtonState.PRESS) client.inGameHud.getDebugHud().toggleDebugHud(); return true;}).cooldown().register(); .action((client,binding,value,action) -> {if (action == ButtonState.PRESS) client.debugHudEntryList.setF3Enabled(!client.debugHudEntryList.isF3Enabled()); return true;}).cooldown().register();
public static final ButtonBinding SLOT_DOWN = new Builder("slot_down").buttons(GLFW_GAMEPAD_BUTTON_DPAD_DOWN) public static final ButtonBinding SLOT_DOWN = new Builder("slot_down").buttons(GLFW_GAMEPAD_BUTTON_DPAD_DOWN)
.action(InputHandlers.handleInventorySlotPad(1)).onlyInInventory().cooldown().register(); .action(InputHandlers.handleInventorySlotPad(1)).onlyInInventory().cooldown().register();
public static final ButtonBinding SLOT_LEFT = new Builder("slot_left").buttons(GLFW_GAMEPAD_BUTTON_DPAD_LEFT) public static final ButtonBinding SLOT_LEFT = new Builder("slot_left").buttons(GLFW_GAMEPAD_BUTTON_DPAD_LEFT)
@@ -413,7 +413,7 @@ public class ButtonBinding {
} }
static { static {
MOVEMENT_CATEGORY = InputManager.registerDefaultCategory("key.categories.movement", category -> category.registerAllBindings( MOVEMENT_CATEGORY = InputManager.registerDefaultCategory("movement", category -> category.registerAllBindings(
ButtonBinding.FORWARD, ButtonBinding.FORWARD,
ButtonBinding.BACK, ButtonBinding.BACK,
ButtonBinding.LEFT, ButtonBinding.LEFT,
@@ -421,12 +421,12 @@ public class ButtonBinding {
ButtonBinding.JUMP, ButtonBinding.JUMP,
ButtonBinding.SNEAK, ButtonBinding.SNEAK,
ButtonBinding.SPRINT)); ButtonBinding.SPRINT));
GAMEPLAY_CATEGORY = InputManager.registerDefaultCategory("key.categories.gameplay", category -> category.registerAllBindings( GAMEPLAY_CATEGORY = InputManager.registerDefaultCategory("gameplay", category -> category.registerAllBindings(
ButtonBinding.ATTACK, ButtonBinding.ATTACK,
ButtonBinding.PICK_BLOCK, ButtonBinding.PICK_BLOCK,
ButtonBinding.USE ButtonBinding.USE
)); ));
INVENTORY_CATEGORY = InputManager.registerDefaultCategory("key.categories.inventory", category -> category.registerAllBindings( INVENTORY_CATEGORY = InputManager.registerDefaultCategory("inventory", category -> category.registerAllBindings(
ButtonBinding.EXIT, ButtonBinding.EXIT,
ButtonBinding.DROP_ITEM, ButtonBinding.DROP_ITEM,
ButtonBinding.HOTBAR_LEFT, ButtonBinding.HOTBAR_LEFT,
@@ -445,9 +445,9 @@ public class ButtonBinding {
ButtonBinding.SLOT_LEFT, ButtonBinding.SLOT_LEFT,
ButtonBinding.SLOT_RIGHT ButtonBinding.SLOT_RIGHT
)); ));
MULTIPLAYER_CATEGORY = InputManager.registerDefaultCategory("key.categories.multiplayer", MULTIPLAYER_CATEGORY = InputManager.registerDefaultCategory("multiplayer",
category -> category.registerAllBindings(ButtonBinding.CHAT, ButtonBinding.PLAYER_LIST)); category -> category.registerAllBindings(ButtonBinding.CHAT, ButtonBinding.PLAYER_LIST));
MISC_CATEGORY = InputManager.registerDefaultCategory("key.categories.misc", category -> category.registerAllBindings( MISC_CATEGORY = InputManager.registerDefaultCategory("misc", category -> category.registerAllBindings(
ButtonBinding.SCREENSHOT, ButtonBinding.SCREENSHOT,
ButtonBinding.TOGGLE_PERSPECTIVE, ButtonBinding.TOGGLE_PERSPECTIVE,
ButtonBinding.PAUSE_GAME, ButtonBinding.PAUSE_GAME,

View File

@@ -38,15 +38,6 @@ public class ButtonCategory {
public ButtonCategory(@NotNull Identifier id) { public ButtonCategory(@NotNull Identifier id) {
this(id, 100); this(id, 100);
} }
@Deprecated
public ButtonCategory(@NotNull org.aperlambda.lambdacommon.Identifier id, int priority) {
this(Identifier.of(id.getNamespace(), id.getName()), priority);
}
@Deprecated
public ButtonCategory(@NotNull org.aperlambda.lambdacommon.Identifier id) {
this(id, 100);
}
public void registerBinding(@NotNull ButtonBinding binding) { public void registerBinding(@NotNull ButtonBinding binding) {
if (this.bindings.contains(binding)) if (this.bindings.contains(binding))
@@ -74,15 +65,12 @@ public class ButtonCategory {
/** /**
* Gets the translated name of this category. * Gets the translated name of this category.
* <p> * <p>
* The translation key should be `modid.identifier_name`. * The translation key should be `key.category.modid.identifier_name`.
* *
* @return the translated name * @return the translated name
*/ */
public @NotNull String getTranslatedName() { public @NotNull String getTranslatedName() {
if (this.id.getNamespace().equals("minecraft")) return I18n.translate("key.category.%s.%s".formatted(id.getNamespace(), id.getPath()));
return I18n.translate(this.id.getPath());
else
return I18n.translate(this.id.getNamespace() + "." + this.id.getPath());
} }
/** /**

View File

@@ -177,7 +177,7 @@ public class InputHandlers {
if (button.getName().equals("take_all")) { if (button.getName().equals("take_all")) {
return false; return false;
} }
slotId = accessor.midnightcontrols$isClickOutsideBounds(x, y, accessor.getX(), accessor.getY(), GLFW_MOUSE_BUTTON_1) ? -999 : -1; slotId = accessor.midnightcontrols$isClickOutsideBounds(x, y, accessor.getX(), accessor.getY()) ? -999 : -1;
} else { } else {
slotId = slot.id; slotId = slot.id;
} }

View File

@@ -420,9 +420,9 @@ public class InputManager {
* @param code the code * @param code the code
* @param category the category of the key binding * @param category the category of the key binding
* @return the key binding * @return the key binding
* @see #makeKeyBinding(Identifier, InputUtil.Type, int, String) * @see #makeKeyBinding(Identifier, InputUtil.Type, int, net.minecraft.client.option.KeyBinding.Category)
*/ */
public static @NotNull KeyBinding makeKeyBinding(@NotNull Identifier id, InputUtil.Type type, int code, @NotNull String category) { public static @NotNull KeyBinding makeKeyBinding(@NotNull Identifier id, InputUtil.Type type, int code, @NotNull KeyBinding.Category category) {
return new KeyBinding(String.format("key.%s.%s", id.getNamespace(), id.getPath()), type, code, category); return new KeyBinding(String.format("key.%s.%s", id.getNamespace(), id.getPath()), type, code, category);
} }
} }

View File

@@ -28,7 +28,7 @@ public interface PressAction {
if (action == ButtonState.REPEAT || client.currentScreen != null) if (action == ButtonState.REPEAT || client.currentScreen != null)
return false; return false;
button.asKeyBinding().ifPresent(binding -> { button.asKeyBinding().ifPresent(binding -> {
if (binding instanceof StickyKeyBinding) if (binding instanceof StickyKeyBinding && binding != client.options.attackKey) // TODO: Properly fix sticky keys so the attack key doesn't need to be a hardcoded exception
binding.setPressed(button.isPressed()); binding.setPressed(button.isPressed());
else else
((KeyBindingAccessor) binding).midnightcontrols$handlePressState(button.isPressed()); ((KeyBindingAccessor) binding).midnightcontrols$handlePressState(button.isPressed());

View File

@@ -9,42 +9,25 @@
package eu.midnightdust.midnightcontrols.client.gui; package eu.midnightdust.midnightcontrols.client.gui;
import com.mojang.blaze3d.pipeline.RenderPipeline;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.textures.GpuTextureView;
import eu.midnightdust.midnightcontrols.ControlsMode;
import eu.midnightdust.midnightcontrols.client.enums.ControllerType; import eu.midnightdust.midnightcontrols.client.enums.ControllerType;
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient; import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig; import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
import eu.midnightdust.midnightcontrols.client.MidnightInput; import eu.midnightdust.midnightcontrols.client.MidnightInput;
import eu.midnightdust.midnightcontrols.client.compat.MidnightControlsCompat; import eu.midnightdust.midnightcontrols.client.compat.MidnightControlsCompat;
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding; import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
import eu.midnightdust.midnightcontrols.client.enums.VirtualMouseSkin;
import eu.midnightdust.midnightcontrols.client.gui.render.UnalignedTexturedQuadGuiElementRenderState;
import eu.midnightdust.midnightcontrols.client.mixin.DrawContextAccessor;
import eu.midnightdust.midnightcontrols.client.util.HandledScreenAccessor; import eu.midnightdust.midnightcontrols.client.util.HandledScreenAccessor;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.client.font.TextRenderer; import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gl.RenderPipelines; import net.minecraft.client.gl.RenderPipelines;
import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.render.state.TexturedQuadGuiElementRenderState;
import net.minecraft.client.render.*;
import net.minecraft.client.resource.language.I18n; import net.minecraft.client.resource.language.I18n;
import net.minecraft.client.texture.Sprite; import net.minecraft.client.texture.Sprite;
import net.minecraft.client.texture.TextureSetup;
import net.minecraft.screen.slot.Slot; import net.minecraft.screen.slot.Slot;
import net.minecraft.text.Text; import net.minecraft.util.Atlases;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.ColorHelper;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.joml.Matrix3x2f;
import org.joml.Matrix4f;
import org.lwjgl.glfw.GLFW; import org.lwjgl.glfw.GLFW;
import java.util.function.Function;
import static eu.midnightdust.midnightcontrols.MidnightControls.id; import static eu.midnightdust.midnightcontrols.MidnightControls.id;
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.client;
/** /**
* Represents the midnightcontrols renderer. * Represents the midnightcontrols renderer.
@@ -211,68 +194,6 @@ public class MidnightControlsRenderer {
private static int getButtonTipWidth(@NotNull String action, @NotNull TextRenderer textRenderer) { private static int getButtonTipWidth(@NotNull String action, @NotNull TextRenderer textRenderer) {
return 15 + 5 + textRenderer.getWidth(action); return 15 + 5 + textRenderer.getWidth(action);
} }
public static void renderWaylandCursor(@NotNull DrawContext context, @NotNull MinecraftClient client) {
if (MidnightControlsConfig.virtualMouse || client.currentScreen == null || MidnightControlsConfig.controlsMode != ControlsMode.CONTROLLER) return;
float mouseX = (float) client.mouse.getX() * client.getWindow().getScaledWidth() / client.getWindow().getWidth();
float mouseY = (float) client.mouse.getY() * client.getWindow().getScaledHeight() / client.getWindow().getHeight();
try {
Identifier spritePath = MidnightControlsClient.WAYLAND_CURSOR_TEXTURE_LIGHT;
if (MidnightControlsConfig.virtualMouseSkin == VirtualMouseSkin.DEFAULT_DARK || MidnightControlsConfig.virtualMouseSkin == VirtualMouseSkin.SECOND_DARK)
spritePath = MidnightControlsClient.WAYLAND_CURSOR_TEXTURE_DARK;
Sprite sprite = client.getGuiAtlasManager().getSprite(spritePath);
drawUnalignedTexturedQuad(RenderPipelines.GUI_TEXTURED, sprite.getAtlasId(), context, mouseX, mouseX + 8, mouseY, mouseY + 8, sprite.getMinU(), sprite.getMaxU(), sprite.getMinV(), sprite.getMaxV());
} catch (IllegalStateException ignored) {}
}
public static void renderVirtualCursor(@NotNull DrawContext context, @NotNull MinecraftClient client) {
if (!MidnightControlsConfig.virtualMouse || (client.currentScreen == null
|| MidnightInput.isScreenInteractive(client.currentScreen)))
return;
float mouseX = (float) client.mouse.getX() * client.getWindow().getScaledWidth() / client.getWindow().getWidth();
float mouseY = (float) client.mouse.getY() * client.getWindow().getScaledHeight() / client.getWindow().getHeight();
boolean hoverSlot = false;
if (client.currentScreen instanceof HandledScreenAccessor inventoryScreen) {
int guiLeft = inventoryScreen.getX();
int guiTop = inventoryScreen.getY();
Slot slot = inventoryScreen.midnightcontrols$getSlotAt(mouseX, mouseY);
if (slot != null) {
mouseX = guiLeft + slot.x;
mouseY = guiTop + slot.y;
hoverSlot = true;
}
}
if (!hoverSlot && client.currentScreen != null) {
var slot = MidnightControlsCompat.getSlotAt(client.currentScreen, (int) mouseX, (int) mouseY);
if (slot != null) {
mouseX = slot.x();
mouseY = slot.y();
hoverSlot = true;
}
}
if (!hoverSlot) {
mouseX -= 8;
mouseY -= 8;
}
try {
Sprite sprite = client.getGuiAtlasManager().getSprite(id(MidnightControlsConfig.virtualMouseSkin.getSpritePath() + (hoverSlot ? "_slot" : "")));
drawUnalignedTexturedQuad(RenderPipelines.GUI_TEXTURED, sprite.getAtlasId(), context, mouseX, mouseX + 16, mouseY, mouseY + 16, sprite.getMinU(), sprite.getMaxU(), sprite.getMinV(), sprite.getMaxV());
} catch (IllegalStateException ignored) {}
}
private static void drawUnalignedTexturedQuad(RenderPipeline pipeline, Identifier texture, DrawContext context, float x1, float x2, float y1, float y2, float u1, float u2, float v1, float v2) {
DrawContextAccessor accessor = (DrawContextAccessor) context;
accessor.getState().addSimpleElement(new UnalignedTexturedQuadGuiElementRenderState(pipeline, TextureSetup.withoutGlTexture(client.getTextureManager().getTexture(texture).getGlTextureView()), new Matrix3x2f(context.getMatrices()), x1, y1, x2, y2, u1, u2, v1, v2, 0xffffffff, accessor.getScissorStack().peekLast()));
}
public record ButtonSize(int length, int height) { public record ButtonSize(int length, int height) {
} }

View File

@@ -64,7 +64,6 @@ public class MidnightControlsSettingsScreen extends SpruceScreen {
private final SpruceOption advancedConfigOption; private final SpruceOption advancedConfigOption;
// Gameplay options // Gameplay options
private final SpruceOption analogMovementOption; private final SpruceOption analogMovementOption;
private final SpruceOption doubleTapToSprintOption;
private final SpruceOption autoJumpOption; private final SpruceOption autoJumpOption;
private final SpruceOption controllerToggleSneakOption; private final SpruceOption controllerToggleSneakOption;
private final SpruceOption controllerToggleSprintOption; private final SpruceOption controllerToggleSprintOption;
@@ -163,7 +162,7 @@ public class MidnightControlsSettingsScreen extends SpruceScreen {
.append(Text.literal(GAMEPAD_TOOL_URL).formatted(Formatting.GOLD)) .append(Text.literal(GAMEPAD_TOOL_URL).formatted(Formatting.GOLD))
.append("),"); .append("),");
private static int searchNextAvailableController(int newId, boolean allowNone) { public static int searchNextAvailableController(int newId, boolean allowNone) {
if ((allowNone && newId == -1) || newId == 0) return newId; if ((allowNone && newId == -1) || newId == 0) return newId;
Controller candidate = Controller.byId(newId); Controller candidate = Controller.byId(newId);
@@ -228,9 +227,6 @@ public class MidnightControlsSettingsScreen extends SpruceScreen {
this.analogMovementOption = new SpruceToggleBooleanOption("midnightcontrols.menu.analog_movement", this.analogMovementOption = new SpruceToggleBooleanOption("midnightcontrols.menu.analog_movement",
() -> MidnightControlsConfig.analogMovement, value -> MidnightControlsConfig.analogMovement = value, () -> MidnightControlsConfig.analogMovement, value -> MidnightControlsConfig.analogMovement = value,
Text.translatable("midnightcontrols.menu.analog_movement.tooltip")); Text.translatable("midnightcontrols.menu.analog_movement.tooltip"));
this.doubleTapToSprintOption = new SpruceToggleBooleanOption("midnightcontrols.menu.double_tap_to_sprint",
() -> MidnightControlsConfig.doubleTapToSprint, value -> MidnightControlsConfig.doubleTapToSprint = value,
Text.translatable("midnightcontrols.menu.double_tap_to_sprint.tooltip"));
this.autoJumpOption = new SpruceToggleBooleanOption("options.autoJump", this.autoJumpOption = new SpruceToggleBooleanOption("options.autoJump",
() -> this.client.options.getAutoJump().getValue(), () -> this.client.options.getAutoJump().getValue(),
newValue -> this.client.options.getAutoJump().setValue(newValue), newValue -> this.client.options.getAutoJump().setValue(newValue),
@@ -409,7 +405,6 @@ public class MidnightControlsSettingsScreen extends SpruceScreen {
var list = new SpruceOptionListWidget(Position.origin(), width, height); var list = new SpruceOptionListWidget(Position.origin(), width, height);
list.setBackground(new MidnightControlsBackground(130)); list.setBackground(new MidnightControlsBackground(130));
list.addSingleOptionEntry(this.analogMovementOption); list.addSingleOptionEntry(this.analogMovementOption);
list.addSingleOptionEntry(this.doubleTapToSprintOption);
list.addSingleOptionEntry(this.controllerToggleSneakOption); list.addSingleOptionEntry(this.controllerToggleSneakOption);
list.addSingleOptionEntry(this.controllerToggleSprintOption); list.addSingleOptionEntry(this.controllerToggleSprintOption);
if (MidnightControls.isExtrasLoaded) list.addSingleOptionEntry(this.fastBlockPlacingOption); if (MidnightControls.isExtrasLoaded) list.addSingleOptionEntry(this.fastBlockPlacingOption);

View File

@@ -12,6 +12,7 @@ package eu.midnightdust.midnightcontrols.client.gui;
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient; import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
import eu.midnightdust.midnightcontrols.client.ring.RingButtonMode; import eu.midnightdust.midnightcontrols.client.ring.RingButtonMode;
import eu.midnightdust.midnightcontrols.client.ring.RingPage; import eu.midnightdust.midnightcontrols.client.ring.RingPage;
import net.minecraft.client.gui.Click;
import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.widget.ButtonWidget; import net.minecraft.client.gui.widget.ButtonWidget;
@@ -79,8 +80,8 @@ public class RingScreen extends Screen {
// } // }
@Override @Override
public boolean mouseReleased(double mouseX, double mouseY, int button) { public boolean mouseReleased(Click click) {
if (ring.getCurrentPage().onClick(width, height, (int) mouseX, (int) mouseY)) { if (ring.getCurrentPage().onClick(width, height, (int) click.x(), (int) click.y())) {
this.close(); this.close();
return true; return true;
} }

View File

@@ -0,0 +1,160 @@
package eu.midnightdust.midnightcontrols.client.gui.config;
import com.google.common.collect.Lists;
import eu.midnightdust.lib.config.EntryInfo;
import eu.midnightdust.lib.config.MidnightConfigListWidget;
import eu.midnightdust.lib.config.MidnightConfigScreen;
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
import eu.midnightdust.midnightcontrols.client.controller.InputManager;
import eu.midnightdust.midnightcontrols.client.gui.MidnightControlsRenderer;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.tooltip.Tooltip;
import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.client.gui.widget.ClickableWidget;
import net.minecraft.client.gui.widget.TextIconButtonWidget;
import net.minecraft.client.input.AbstractInput;
import net.minecraft.text.MutableText;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import net.minecraft.util.Identifier;
import org.jetbrains.annotations.Nullable;
import org.thinkingstudio.obsidianui.SpruceTexts;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
public class ControllerBindingButton extends ButtonWidget implements ControlsInput {
private static final int[] UNBOUND = new int[]{-1};
static boolean waiting = false;
static List<Integer> currentButtons = new ArrayList<>();
private int iconWidth;
public static void add(ButtonBinding binding, MidnightConfigListWidget list, MidnightConfigScreen screen) {
ControllerBindingButton editButton = new ControllerBindingButton(screen.width - 185 + 22, 0, 128, 20, binding);
TextIconButtonWidget resetButton = TextIconButtonWidget.builder(Text.translatable("controls.reset"), (button -> {
MidnightControlsConfig.setButtonBinding(binding, binding.getDefaultButton());
MidnightControlsClient.input.beginControlsInput(null);
editButton.updateMessage(false);
}), true).texture(Identifier.of("midnightlib","icon/reset"), 12, 12).dimension(20, 20).build();
resetButton.setPosition(screen.width - 205 + 150 + 25, 0);
editButton.resetButton = resetButton;
editButton.updateMessage(false);
EntryInfo info = new EntryInfo(null, screen.modid);
TextIconButtonWidget unbindButton = TextIconButtonWidget.builder(Text.translatable("midnightcontrols.narrator.unbound", binding.getText()), (button -> {
MidnightControlsConfig.setButtonBinding(binding, UNBOUND);
MidnightControlsClient.input.beginControlsInput(null);
editButton.updateMessage(false);
}), true).texture(Identifier.of("midnightcontrols","icon/unbind"), 12, 12).dimension(20, 20).build();
unbindButton.setPosition(screen.width - 205 + 20, 0);
unbindButton.setTooltip(Tooltip.of(SpruceTexts.GUI_UNBIND));
unbindButton.active = !binding.isNotBound();
editButton.unbindButton = unbindButton;
list.addButton(Lists.newArrayList(editButton, resetButton, unbindButton), Text.translatable(binding.getTranslationKey()), info);
}
private final ButtonBinding binding;
private @Nullable ClickableWidget resetButton;
private @Nullable ClickableWidget unbindButton;
public ControllerBindingButton(int x, int y, int width, int height, ButtonBinding binding) {
super(x, y, width, height, binding.getText(), (button) -> {},
(textSupplier) -> binding.isNotBound() ? Text.translatable("narrator.controls.unbound", binding.getTranslationKey()) : Text.translatable("narrator.controls.bound", binding.getTranslationKey(), textSupplier.get()));
this.binding = binding;
updateMessage(false);
}
@Override
public void onPress(AbstractInput input) {
MidnightControlsClient.input.beginControlsInput(this);
this.updateMessage(true);
}
public void updateMessage(boolean focused) {
AtomicBoolean hasConflicts = new AtomicBoolean(false);
MutableText conflictingBindings = Text.empty();
if (focused) this.setMessage(Text.literal("> ").append(getTranslatedButtons().copy().formatted(Formatting.WHITE, Formatting.UNDERLINE)).append(" <").formatted(Formatting.YELLOW));
else {
this.setMessage(getTranslatedButtons());
if (!this.binding.isNotBound()) {
InputManager.streamBindings().forEach(keyBinding -> {
if (keyBinding != this.binding && this.binding.equals(keyBinding)) {
if (hasConflicts.get()) conflictingBindings.append(", ");
hasConflicts.set(true);
conflictingBindings.append(Text.translatable(keyBinding.getTranslationKey()));
}
});
}
}
if (this.resetButton != null) this.resetButton.active = !this.binding.isDefault();
if (this.unbindButton != null) this.unbindButton.active = !binding.isNotBound();
if (hasConflicts.get()) {
this.setMessage(Text.literal("[ ").append(this.getMessage().copy().formatted(Formatting.WHITE)).append(" ]").formatted(Formatting.RED));
this.setTooltip(Tooltip.of(Text.translatable("controls.keybinds.duplicateKeybinds", conflictingBindings)));
} else {
this.setTooltip(null);
}
}
private Text getTranslatedButtons() {
return this.binding.isNotBound() ? SpruceTexts.NOT_BOUND.copy() :
(binding.getButton().length > 0 ? ButtonBinding.getLocalizedButtonName(binding.getButton()[0]) : Text.literal("..."));
}
@Override
public void drawMessage(DrawContext context, TextRenderer textRenderer, int color) {
if (this.binding.getButton().length < 2) super.drawMessage(context, textRenderer, color);
}
@Override
protected void renderWidget(DrawContext context, int mouseX, int mouseY, float deltaTicks) {
super.renderWidget(context, mouseX, mouseY, deltaTicks);
int x = this.getX();
if (this.binding.getButton().length > 1) {
x += (this.width / 2 - iconWidth / 2) - 4;
}
var size = MidnightControlsRenderer.drawButton(context, x, this.getY(), this.binding, MinecraftClient.getInstance());
iconWidth = size.length();
}
@Override
public void finishBindingEdit(int... buttons) {
MidnightControlsConfig.setButtonBinding(binding, buttons);
updateMessage(false);
}
@Override
public void update() {
this.updateMessage(true);
}
@Override
public void setWaiting(boolean value) {
waiting = value;
}
@Override
public boolean isWaiting() {
return waiting;
}
@Override
public List<Integer> getCurrentButtons() {
return currentButtons;
}
@Override
public ButtonBinding getFocusedBinding() {
return this.binding;
}
}

View File

@@ -0,0 +1,64 @@
package eu.midnightdust.midnightcontrols.client.gui.config;
import eu.midnightdust.lib.config.EntryInfo;
import eu.midnightdust.lib.config.MidnightConfigListWidget;
import eu.midnightdust.lib.config.MidnightConfigScreen;
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
import eu.midnightdust.midnightcontrols.client.controller.Controller;
import net.minecraft.client.gui.tooltip.Tooltip;
import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.client.gui.widget.TextIconButtonWidget;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import net.minecraft.util.Identifier;
import org.lwjgl.glfw.GLFW;
import org.thinkingstudio.obsidianui.SpruceTexts;
import java.util.List;
import static eu.midnightdust.midnightcontrols.client.gui.MidnightControlsSettingsScreen.searchNextAvailableController;
public class ControllerSelectionButton {
public static void add(MidnightConfigListWidget list, MidnightConfigScreen screen, boolean second) {
TextIconButtonWidget resetButton = TextIconButtonWidget.builder(Text.translatable("controls.reset"), (button -> {
if (second) MidnightControlsConfig.secondControllerID = -1;
else MidnightControlsConfig.controllerID = 0;
screen.updateList();
}), true).texture(Identifier.of("midnightlib","icon/reset"), 12, 12).dimension(20, 20).build();
resetButton.setPosition(screen.width - 205 + 150 + 25, 0);
ButtonWidget editButton = ButtonWidget.builder(getControllerName(second),
button -> {
int id = second ? MidnightControlsConfig.getSecondController().map(Controller::id).orElse(-1) : MidnightControlsConfig.getController().id();
id += 1;
if (id > GLFW.GLFW_JOYSTICK_LAST)
id = GLFW.GLFW_JOYSTICK_1;
id = searchNextAvailableController(id, second);
if (second) {
MidnightControlsConfig.setSecondController(Controller.byId(id));
} else {
MidnightControlsConfig.setController(Controller.byId(id));
}
if (MidnightControlsConfig.debug && id != -1) System.out.println(Controller.byId(id).getName() + "'s Controller GUID: " + Controller.byId(id).getGuid());
resetButton.active = second ? MidnightControlsConfig.getSecondController().isPresent() : false;
button.setMessage(getControllerName(second));
}).dimensions(screen.width - 185, 0, 150, 20).build();
resetButton.active = second ? MidnightControlsConfig.getSecondController().isPresent() : false;
if (second) editButton.setTooltip(Tooltip.of(Text.translatable("midnightcontrols.menu.controller2.tooltip")));
list.addButton(List.of(editButton, resetButton), Text.translatable(second ? "midnightcontrols.menu.controller2" : "midnightcontrols.menu.controller"), new EntryInfo(null, screen.modid));
}
private static Text getControllerName(boolean second) {
if (second && MidnightControlsConfig.getSecondController().isEmpty()) return SpruceTexts.OPTIONS_OFF.copyContentOnly().formatted(Formatting.RED);
var controller = second ? MidnightControlsConfig.getSecondController().get() : MidnightControlsConfig.getController();
var controllerName = controller.getName();
if (!controller.isConnected())
return Text.literal(controllerName).formatted(Formatting.RED);
else if (!controller.isGamepad())
return Text.literal(controllerName).formatted(Formatting.GOLD);
else
return Text.literal(controllerName);
}
}

View File

@@ -0,0 +1,18 @@
package eu.midnightdust.midnightcontrols.client.gui.config;
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
import java.util.List;
public interface ControlsInput {
void setWaiting(boolean value);
boolean isWaiting();
List<Integer> getCurrentButtons();
ButtonBinding getFocusedBinding();
void finishBindingEdit(int[] buttons);
default void update() {};
}

View File

@@ -0,0 +1,24 @@
package eu.midnightdust.midnightcontrols.client.gui.cursor;
import com.mojang.blaze3d.pipeline.RenderPipeline;
import eu.midnightdust.midnightcontrols.client.mixin.DrawContextAccessor;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.cursor.Cursor;
import net.minecraft.client.texture.TextureSetup;
import net.minecraft.util.Identifier;
import org.jetbrains.annotations.NotNull;
import org.joml.Matrix3x2f;
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.client;
public abstract class CursorRenderer {
public static Cursor currentCursorStyle = Cursor.DEFAULT;
public abstract void renderCursor(@NotNull DrawContext context, @NotNull MinecraftClient client);
public static void drawUnalignedTexturedQuad(RenderPipeline pipeline, Identifier texture, DrawContext context, float x1, float x2, float y1, float y2, float u1, float u2, float v1, float v2) {
DrawContextAccessor accessor = (DrawContextAccessor) context;
accessor.getState().addSimpleElement(new UnalignedTexturedQuadGuiElementRenderState(pipeline, TextureSetup.withoutGlTexture(client.getTextureManager().getTexture(texture).getGlTextureView()), new Matrix3x2f(context.getMatrices()), x1, y1, x2, y2, u1, u2, v1, v2, 0xffffffff, accessor.getScissorStack().peekLast()));
}
}

View File

@@ -1,4 +1,4 @@
package eu.midnightdust.midnightcontrols.client.gui.render; package eu.midnightdust.midnightcontrols.client.gui.cursor;
import com.mojang.blaze3d.pipeline.RenderPipeline; import com.mojang.blaze3d.pipeline.RenderPipeline;
import net.fabricmc.api.EnvType; import net.fabricmc.api.EnvType;
@@ -17,11 +17,11 @@ public record UnalignedTexturedQuadGuiElementRenderState(RenderPipeline pipeline
} }
@Override @Override
public void setupVertices(VertexConsumer vertices, float depth) { public void setupVertices(VertexConsumer vertices) {
vertices.vertex(pose(), x1(), y1(), depth).texture(u1(), v1()).color(color()); vertices.vertex(pose(), x1(), y1()).texture(u1(), v1()).color(color());
vertices.vertex(pose(), x1(), y2(), depth).texture(u1(), v2()).color(color()); vertices.vertex(pose(), x1(), y2()).texture(u1(), v2()).color(color());
vertices.vertex(pose(), x2(), y2(), depth).texture(u2(), v2()).color(color()); vertices.vertex(pose(), x2(), y2()).texture(u2(), v2()).color(color());
vertices.vertex(pose(), x2(), y1(), depth).texture(u2(), v1()).color(color()); vertices.vertex(pose(), x2(), y1()).texture(u2(), v1()).color(color());
} }
@Nullable @Nullable

View File

@@ -0,0 +1,67 @@
package eu.midnightdust.midnightcontrols.client.gui.cursor;
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
import eu.midnightdust.midnightcontrols.client.MidnightInput;
import eu.midnightdust.midnightcontrols.client.compat.MidnightControlsCompat;
import eu.midnightdust.midnightcontrols.client.util.HandledScreenAccessor;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gl.RenderPipelines;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.texture.Sprite;
import net.minecraft.screen.slot.Slot;
import net.minecraft.util.Atlases;
import org.jetbrains.annotations.NotNull;
import static eu.midnightdust.midnightcontrols.MidnightControls.id;
public class VirtualCursorRenderer extends CursorRenderer {
private static final VirtualCursorRenderer INSTANCE = new VirtualCursorRenderer();
public static VirtualCursorRenderer getInstance() {
return INSTANCE;
}
public void renderCursor(@NotNull DrawContext context, @NotNull MinecraftClient client) {
if (!MidnightControlsConfig.virtualMouse || (client.currentScreen == null
|| MidnightInput.isScreenInteractive(client.currentScreen)))
return;
float mouseX = (float) client.mouse.getX() * client.getWindow().getScaledWidth() / client.getWindow().getWidth();
float mouseY = (float) client.mouse.getY() * client.getWindow().getScaledHeight() / client.getWindow().getHeight();
boolean hoverSlot = false;
if (client.currentScreen instanceof HandledScreenAccessor inventoryScreen) {
int guiLeft = inventoryScreen.getX();
int guiTop = inventoryScreen.getY();
Slot slot = inventoryScreen.midnightcontrols$getSlotAt(mouseX, mouseY);
if (slot != null) {
mouseX = guiLeft + slot.x;
mouseY = guiTop + slot.y;
hoverSlot = true;
}
}
if (!hoverSlot && client.currentScreen != null) {
var slot = MidnightControlsCompat.getSlotAt(client.currentScreen, (int) mouseX, (int) mouseY);
if (slot != null) {
mouseX = slot.x();
mouseY = slot.y();
hoverSlot = true;
}
}
if (!hoverSlot) {
mouseX -= 8;
mouseY -= 8;
}
try {
Sprite sprite = client.getAtlasManager().getAtlasTexture(Atlases.GUI).getSprite(id(MidnightControlsConfig.virtualMouseSkin.getSpritePath() + (hoverSlot ? "_slot" : "")));
drawUnalignedTexturedQuad(RenderPipelines.GUI_TEXTURED, sprite.getAtlasId(), context, mouseX, mouseX + 16, mouseY, mouseY + 16, sprite.getMinU(), sprite.getMaxU(), sprite.getMinV(), sprite.getMaxV());
} catch (IllegalStateException ignored) {}
}
}

View File

@@ -0,0 +1,61 @@
package eu.midnightdust.midnightcontrols.client.gui.cursor;
import eu.midnightdust.midnightcontrols.ControlsMode;
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
import eu.midnightdust.midnightcontrols.client.enums.VirtualMouseSkin;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gl.RenderPipelines;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.cursor.StandardCursors;
import net.minecraft.client.texture.Sprite;
import net.minecraft.util.Atlases;
import net.minecraft.util.Identifier;
import org.jetbrains.annotations.NotNull;
import static eu.midnightdust.midnightcontrols.MidnightControls.id;
public class WaylandCursorRenderer extends CursorRenderer {
private static final WaylandCursorRenderer INSTANCE = new WaylandCursorRenderer();
public static final Identifier WAYLAND_CURSOR_ARROW_LIGHT = id("cursor/light/mouse_arrow");
public static final Identifier WAYLAND_CURSOR_ARROW_DARK = id("cursor/dark/mouse_arrow");
public static final Identifier WAYLAND_CURSOR_POINTING_LIGHT = id("cursor/light/mouse_pointing_hand");
public static final Identifier WAYLAND_CURSOR_POINTING_DARK = id("cursor/dark/mouse_pointing_hand");
public static final Identifier WAYLAND_CURSOR_IBEAM_LIGHT = id("cursor/light/mouse_ibeam");
public static final Identifier WAYLAND_CURSOR_IBEAM_DARK = id("cursor/dark/mouse_ibeam");
public static final Identifier WAYLAND_CURSOR_RESIZE_VERTICAL_LIGHT = id("cursor/light/mouse_resize_vertical");
public static final Identifier WAYLAND_CURSOR_REZIZE_VERTICAL_DARK = id("cursor/dark/mouse_resize_vertical");
public static final Identifier WAYLAND_CURSOR_RESIZE_HORIZONTAL_LIGHT = id("cursor/light/mouse_resize_horizontal");
public static final Identifier WAYLAND_CURSOR_REZIZE_HORIZONTAL_DARK = id("cursor/dark/mouse_resize_horizontal");
public static final Identifier WAYLAND_CURSOR_NOT_ALLOWED_LIGHT = id("cursor/light/mouse_not_allowed");
public static final Identifier WAYLAND_CURSOR_NOT_ALLOWED_DARK = id("cursor/dark/mouse_not_allowed");
public static WaylandCursorRenderer getInstance() {
return INSTANCE;
}
public void renderCursor(@NotNull DrawContext context, @NotNull MinecraftClient client) {
if (MidnightControlsConfig.virtualMouse || client.currentScreen == null || MidnightControlsConfig.controlsMode != ControlsMode.CONTROLLER) return;
float mouseX = (float) client.mouse.getX() * client.getWindow().getScaledWidth() / client.getWindow().getWidth();
float mouseY = (float) client.mouse.getY() * client.getWindow().getScaledHeight() / client.getWindow().getHeight();
try {
Sprite sprite = getSprite(client);
drawUnalignedTexturedQuad(RenderPipelines.GUI_TEXTURED, sprite.getAtlasId(), context, mouseX - 2, mouseX + 6, mouseY - 2, mouseY + 6, sprite.getMinU(), sprite.getMaxU(), sprite.getMinV(), sprite.getMaxV());
} catch (IllegalStateException ignored) {}
}
private static Sprite getSprite(@NotNull MinecraftClient client) {
boolean isDark = MidnightControlsConfig.virtualMouseSkin == VirtualMouseSkin.DEFAULT_DARK || MidnightControlsConfig.virtualMouseSkin == VirtualMouseSkin.SECOND_DARK;
Identifier spritePath;
if (CursorRenderer.currentCursorStyle == StandardCursors.POINTING_HAND) spritePath = isDark ? WAYLAND_CURSOR_POINTING_DARK : WAYLAND_CURSOR_POINTING_LIGHT;
else if (CursorRenderer.currentCursorStyle == StandardCursors.IBEAM) spritePath = isDark ? WAYLAND_CURSOR_IBEAM_DARK : WAYLAND_CURSOR_IBEAM_LIGHT;
else if (CursorRenderer.currentCursorStyle == StandardCursors.RESIZE_NS) spritePath = isDark ? WAYLAND_CURSOR_REZIZE_VERTICAL_DARK : WAYLAND_CURSOR_RESIZE_VERTICAL_LIGHT;
else if (CursorRenderer.currentCursorStyle == StandardCursors.RESIZE_EW) spritePath = isDark ? WAYLAND_CURSOR_REZIZE_HORIZONTAL_DARK : WAYLAND_CURSOR_RESIZE_HORIZONTAL_LIGHT;
else if (CursorRenderer.currentCursorStyle == StandardCursors.NOT_ALLOWED) spritePath = isDark ? WAYLAND_CURSOR_NOT_ALLOWED_DARK : WAYLAND_CURSOR_NOT_ALLOWED_LIGHT;
else spritePath = isDark ? WAYLAND_CURSOR_ARROW_DARK : WAYLAND_CURSOR_ARROW_LIGHT;
return client.getAtlasManager().getAtlasTexture(Atlases.GUI).getSprite(spritePath);
}
}

View File

@@ -12,6 +12,7 @@ package eu.midnightdust.midnightcontrols.client.gui.widget;
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig; import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding; import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
import eu.midnightdust.midnightcontrols.client.controller.InputManager; import eu.midnightdust.midnightcontrols.client.controller.InputManager;
import eu.midnightdust.midnightcontrols.client.gui.config.ControlsInput;
import org.thinkingstudio.obsidianui.Position; import org.thinkingstudio.obsidianui.Position;
import org.thinkingstudio.obsidianui.SpruceTexts; import org.thinkingstudio.obsidianui.SpruceTexts;
import org.thinkingstudio.obsidianui.widget.SpruceButtonWidget; import org.thinkingstudio.obsidianui.widget.SpruceButtonWidget;
@@ -29,11 +30,11 @@ import java.util.stream.Collectors;
/** /**
* Represents the controls screen. * Represents the controls screen.
*/ */
public class ControllerControlsWidget extends SpruceContainerWidget { public class ControllerControlsWidget extends SpruceContainerWidget implements ControlsInput {
private SpruceButtonWidget resetButton; private SpruceButtonWidget resetButton;
public ButtonBinding focusedBinding; ButtonBinding focusedBinding = null;
public boolean waiting = false; boolean waiting = false;
public List<Integer> currentButtons = new ArrayList<>(); List<Integer> currentButtons = new ArrayList<>();
public ControllerControlsWidget(Position position, int width, int height) { public ControllerControlsWidget(Position position, int width, int height) {
super(position, width, height); super(position, width, height);
@@ -66,4 +67,24 @@ public class ControllerControlsWidget extends SpruceContainerWidget {
MidnightControlsConfig.setButtonBinding(this.focusedBinding, buttons); MidnightControlsConfig.setButtonBinding(this.focusedBinding, buttons);
this.focusedBinding = null; this.focusedBinding = null;
} }
@Override
public void setWaiting(boolean value) {
this.waiting = value;
}
@Override
public boolean isWaiting() {
return this.waiting;
}
@Override
public List<Integer> getCurrentButtons() {
return currentButtons;
}
@Override
public ButtonBinding getFocusedBinding() {
return focusedBinding;
}
} }

View File

@@ -15,6 +15,9 @@ import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding;
import eu.midnightdust.midnightcontrols.client.controller.ButtonCategory; import eu.midnightdust.midnightcontrols.client.controller.ButtonCategory;
import eu.midnightdust.midnightcontrols.client.controller.InputManager; import eu.midnightdust.midnightcontrols.client.controller.InputManager;
import net.minecraft.client.gl.RenderPipelines; import net.minecraft.client.gl.RenderPipelines;
import net.minecraft.client.gui.Click;
import net.minecraft.client.input.KeyInput;
import net.minecraft.client.input.MouseInput;
import net.minecraft.client.render.RenderLayer; import net.minecraft.client.render.RenderLayer;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import org.thinkingstudio.obsidianui.Position; import org.thinkingstudio.obsidianui.Position;
@@ -175,7 +178,7 @@ public class ControlsListWidget extends SpruceEntryListWidget<ControlsListWidget
} }
element = it.next(); element = it.next();
} while (!element.mouseClicked(mouseX, mouseY, button)); } while (!element.mouseClicked(new Click(mouseX, mouseY, new MouseInput(button, 0)), false));
this.setFocused(element); this.setFocused(element);
if (button == GLFW.GLFW_MOUSE_BUTTON_1) if (button == GLFW.GLFW_MOUSE_BUTTON_1)
@@ -187,18 +190,18 @@ public class ControlsListWidget extends SpruceEntryListWidget<ControlsListWidget
@Override @Override
protected boolean onMouseRelease(double mouseX, double mouseY, int button) { protected boolean onMouseRelease(double mouseX, double mouseY, int button) {
this.dragging = false; this.dragging = false;
return this.hoveredElement(mouseX, mouseY).filter(element -> element.mouseReleased(mouseX, mouseY, button)).isPresent(); return this.hoveredElement(mouseX, mouseY).filter(element -> element.mouseReleased(new Click(mouseX, mouseY, new MouseInput(button, 0)))).isPresent();
} }
@Override @Override
protected boolean onMouseDrag(double mouseX, double mouseY, int button, double deltaX, double deltaY) { protected boolean onMouseDrag(double mouseX, double mouseY, int button, double deltaX, double deltaY) {
return this.getFocused() != null && this.dragging && button == GLFW.GLFW_MOUSE_BUTTON_1 return this.getFocused() != null && this.dragging && button == GLFW.GLFW_MOUSE_BUTTON_1
&& this.getFocused().mouseDragged(mouseX, mouseY, button, deltaX, deltaY); && this.getFocused().mouseDragged(new Click(mouseX, mouseY, new MouseInput(button, 0)), deltaX, deltaY);
} }
@Override @Override
protected boolean onKeyPress(int keyCode, int scanCode, int modifiers) { protected boolean onKeyPress(int keyCode, int scanCode, int modifiers) {
return this.focused != null && this.focused.keyPressed(keyCode, scanCode, modifiers); return this.focused != null && this.focused.keyPressed(new KeyInput(keyCode, scanCode, modifiers));
} }
/* Navigation */ /* Navigation */

View File

@@ -56,12 +56,9 @@ public abstract class ClientPlayerEntityMixin extends AbstractClientPlayerEntity
@Shadow @Shadow
protected abstract boolean isCamera(); protected abstract boolean isCamera();
@Shadow protected int ticksLeftToDoubleTapSprint;
@Inject(method = "move(Lnet/minecraft/entity/MovementType;Lnet/minecraft/util/math/Vec3d;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/AbstractClientPlayerEntity;move(Lnet/minecraft/entity/MovementType;Lnet/minecraft/util/math/Vec3d;)V")) @Inject(method = "move(Lnet/minecraft/entity/MovementType;Lnet/minecraft/util/math/Vec3d;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/AbstractClientPlayerEntity;move(Lnet/minecraft/entity/MovementType;Lnet/minecraft/util/math/Vec3d;)V"))
public void onMove(MovementType type, Vec3d movement, CallbackInfo ci) { public void onMove(MovementType type, Vec3d movement, CallbackInfo ci) {
if (!MidnightControlsConfig.doubleTapToSprint) ticksLeftToDoubleTapSprint = 0;
if (!MidnightControls.isExtrasLoaded) return; if (!MidnightControls.isExtrasLoaded) return;
if (type == MovementType.SELF) { if (type == MovementType.SELF) {
if (this.getAbilities().flying && (!MidnightControlsConfig.flyDrifting || !MidnightControlsConfig.verticalFlyDrifting)) { if (this.getAbilities().flying && (!MidnightControlsConfig.flyDrifting || !MidnightControlsConfig.verticalFlyDrifting)) {

View File

@@ -0,0 +1,17 @@
package eu.midnightdust.midnightcontrols.client.mixin;
import eu.midnightdust.midnightcontrols.client.gui.cursor.CursorRenderer;
import net.minecraft.client.gui.cursor.Cursor;
import net.minecraft.client.util.Window;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(Cursor.class)
public abstract class CursorMixin {
@Inject(method = "applyTo", at = @At("TAIL"))
public void midnightcontrols$applyCursorStyle(Window window, CallbackInfo ci) {
CursorRenderer.currentCursorStyle = ((Cursor) (Object) this);
}
}

View File

@@ -9,6 +9,7 @@
package eu.midnightdust.midnightcontrols.client.mixin; package eu.midnightdust.midnightcontrols.client.mixin;
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
import eu.midnightdust.midnightcontrols.client.gui.MidnightControlsSettingsScreen; import eu.midnightdust.midnightcontrols.client.gui.MidnightControlsSettingsScreen;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.Screen;
@@ -34,7 +35,7 @@ import static eu.midnightdust.midnightcontrols.MidnightControls.id;
public abstract class GameOptionsScreenMixin extends Screen { public abstract class GameOptionsScreenMixin extends Screen {
@Shadow @Nullable protected OptionListWidget body; @Shadow @Nullable protected OptionListWidget body;
@Unique TextIconButtonWidget midnightcontrols$button = TextIconButtonWidget.builder(Text.translatable("midnightcontrols.menu.title.controller"), @Unique TextIconButtonWidget midnightcontrols$button = TextIconButtonWidget.builder(Text.translatable("midnightcontrols.menu.title.controller"),
(button -> this.client.setScreen(new MidnightControlsSettingsScreen(this, false))), true) (button -> this.client.setScreen(MidnightControlsConfig.getScreen(this, "midnightcontrols"))), true)
.dimension(20,20).texture(id("icon/controller"), 20, 20).build(); .dimension(20,20).texture(id("icon/controller"), 20, 20).build();
protected GameOptionsScreenMixin(Text title) { protected GameOptionsScreenMixin(Text title) {

View File

@@ -14,7 +14,8 @@ import com.mojang.blaze3d.systems.RenderSystem;
import eu.midnightdust.midnightcontrols.ControlsMode; import eu.midnightdust.midnightcontrols.ControlsMode;
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient; import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig; import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
import eu.midnightdust.midnightcontrols.client.gui.MidnightControlsRenderer; import eu.midnightdust.midnightcontrols.client.gui.cursor.VirtualCursorRenderer;
import eu.midnightdust.midnightcontrols.client.gui.cursor.WaylandCursorRenderer;
import eu.midnightdust.midnightcontrols.client.touch.TouchUtils; import eu.midnightdust.midnightcontrols.client.touch.TouchUtils;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.DrawContext;
@@ -39,12 +40,11 @@ public abstract class GameRendererMixin {
} }
@Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/Screen;renderWithTooltip(Lnet/minecraft/client/gui/DrawContext;IIF)V", shift = At.Shift.AFTER)) @Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/Screen;renderWithTooltip(Lnet/minecraft/client/gui/DrawContext;IIF)V", shift = At.Shift.AFTER))
private void midnightcontrols$renderVirtualCursor(RenderTickCounter tickCounter, boolean tick, CallbackInfo ci, @Local DrawContext drawContext) { private void midnightcontrols$renderVirtualCursor(RenderTickCounter tickCounter, boolean tick, CallbackInfo ci, @Local DrawContext drawContext) {
MidnightControlsRenderer.renderVirtualCursor(drawContext, client); VirtualCursorRenderer.getInstance().renderCursor(drawContext, client);
if (MidnightControlsClient.isWayland) MidnightControlsRenderer.renderWaylandCursor(drawContext, client); if (MidnightControlsClient.isWayland) WaylandCursorRenderer.getInstance().renderCursor(drawContext, client);
//drawContext.draw();
} }
@Inject(at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/GameRenderer;renderHand(FZLorg/joml/Matrix4f;)V"), method = "renderWorld") @Inject(at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/GameRenderer;renderHand(FZLorg/joml/Matrix4f;)V"), method = "renderWorld")
private void midnigtcontrols$captureMatrices(RenderTickCounter tickCounter, CallbackInfo ci, @Local(ordinal = 1) Matrix4f projectionMatrix, @Local(ordinal = 2) Matrix4f worldSpaceMatrix) { private void midnigtcontrols$captureMatrices(RenderTickCounter tickCounter, CallbackInfo ci, @Local(ordinal = 0) Matrix4f projectionMatrix, @Local(ordinal = 1) Matrix4f worldSpaceMatrix) {
TouchUtils.lastProjMat.set(projectionMatrix); TouchUtils.lastProjMat.set(projectionMatrix);
TouchUtils.lastModMat.set(RenderSystem.getModelViewMatrix()); TouchUtils.lastModMat.set(RenderSystem.getModelViewMatrix());
TouchUtils.lastWorldSpaceMatrix.set(worldSpaceMatrix); TouchUtils.lastWorldSpaceMatrix.set(worldSpaceMatrix);

View File

@@ -46,7 +46,7 @@ public abstract class HandledScreenMixin implements HandledScreenAccessor {
public abstract Slot midnightcontrols$getSlotAt(double posX, double posY); public abstract Slot midnightcontrols$getSlotAt(double posX, double posY);
@Invoker("isClickOutsideBounds") @Invoker("isClickOutsideBounds")
public abstract boolean midnightcontrols$isClickOutsideBounds(double mouseX, double mouseY, int x, int y, int button); public abstract boolean midnightcontrols$isClickOutsideBounds(double mouseX, double mouseY, int left, int top);
@Invoker("onMouseClick") @Invoker("onMouseClick")

View File

@@ -0,0 +1,12 @@
package eu.midnightdust.midnightcontrols.client.mixin;
import net.minecraft.client.Keyboard;
import net.minecraft.client.input.KeyInput;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Invoker;
@Mixin(Keyboard.class)
public interface KeyboardAccessor {
@Invoker("onKey")
void midnightcontrols$onKey(long window, int action, KeyInput input);
}

View File

@@ -56,7 +56,7 @@ public abstract class MinecraftClientMixin {
@Shadow public abstract void setScreen(Screen screen); @Shadow public abstract void setScreen(Screen screen);
@Shadow public int attackCooldown; @Shadow protected int attackCooldown;
@Shadow protected abstract void handleInputEvents(); @Shadow protected abstract void handleInputEvents();
@@ -77,7 +77,7 @@ public abstract class MinecraftClientMixin {
if (!MidnightControlsFeature.FAST_BLOCK_PLACING.isAvailable()) if (!MidnightControlsFeature.FAST_BLOCK_PLACING.isAvailable())
return; return;
if (this.midnightcontrols$lastPos == null) if (this.midnightcontrols$lastPos == null)
this.midnightcontrols$lastPos = this.player.getPos(); this.midnightcontrols$lastPos = this.player.getEntityPos();
int cooldown = this.itemUseCooldown; int cooldown = this.itemUseCooldown;
BlockHitResult hitResult; BlockHitResult hitResult;
@@ -106,7 +106,7 @@ public abstract class MinecraftClientMixin {
// this.itemUseCooldown = 0; // this.itemUseCooldown = 0;
// } // }
// } // }
this.midnightcontrols$lastPos = this.player.getPos(); this.midnightcontrols$lastPos = this.player.getEntityPos();
} }
@Inject(at = @At("TAIL"), method = "setScreen") @Inject(at = @At("TAIL"), method = "setScreen")

View File

@@ -1,6 +1,7 @@
package eu.midnightdust.midnightcontrols.client.mixin; package eu.midnightdust.midnightcontrols.client.mixin;
import net.minecraft.client.Mouse; import net.minecraft.client.Mouse;
import net.minecraft.client.input.MouseInput;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Invoker; import org.spongepowered.asm.mixin.gen.Invoker;
@@ -9,5 +10,5 @@ public interface MouseAccessor {
@Invoker("onCursorPos") @Invoker("onCursorPos")
void midnightcontrols$onCursorPos(long window, double x, double y); void midnightcontrols$onCursorPos(long window, double x, double y);
@Invoker("onMouseButton") @Invoker("onMouseButton")
void midnightcontrols$onMouseButton(long window, int button, int action, int mods); void midnightcontrols$onMouseButton(long window, MouseInput input, int action);
} }

View File

@@ -17,6 +17,8 @@ import eu.midnightdust.midnightcontrols.client.touch.TouchInput;
import eu.midnightdust.midnightcontrols.client.touch.TouchUtils; import eu.midnightdust.midnightcontrols.client.touch.TouchUtils;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.client.Mouse; import net.minecraft.client.Mouse;
import net.minecraft.client.gui.Click;
import net.minecraft.client.input.MouseInput;
import net.minecraft.client.util.GlfwUtil; import net.minecraft.client.util.GlfwUtil;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.item.ThrowablePotionItem; import net.minecraft.item.ThrowablePotionItem;
@@ -64,12 +66,12 @@ public abstract class MouseMixin implements MouseAccessor {
@Shadow private boolean leftButtonClicked; @Shadow private boolean leftButtonClicked;
@Inject(method = "onMouseButton", at = @At(value = "HEAD"), cancellable = true) @Inject(method = "onMouseButton", at = @At(value = "HEAD"), cancellable = true)
private void midnightcontrols$onMouseButton(long window, int button, int action, int mods, CallbackInfo ci) { private void midnightcontrols$onMouseButton(long window, MouseInput input, int action, CallbackInfo ci) {
if (window != this.client.getWindow().getHandle()) return; if (window != this.client.getWindow().getHandle()) return;
if (action == 1 && button == GLFW.GLFW_MOUSE_BUTTON_4 && client.currentScreen != null) { if (action == 1 && input.button() == GLFW.GLFW_MOUSE_BUTTON_4 && client.currentScreen != null) {
MidnightControlsClient.input.tryGoBack(client.currentScreen); MidnightControlsClient.input.tryGoBack(client.currentScreen);
} }
else if ((client.currentScreen == null && doMixedInput() || client.currentScreen instanceof TouchscreenOverlay) && client.player != null && button == GLFW_MOUSE_BUTTON_1) { else if ((client.currentScreen == null && doMixedInput() || client.currentScreen instanceof TouchscreenOverlay) && client.player != null && input.button() == GLFW_MOUSE_BUTTON_1) {
double mouseX = x / client.getWindow().getScaleFactor(); double mouseX = x / client.getWindow().getScaleFactor();
double mouseY = y / client.getWindow().getScaleFactor(); double mouseY = y / client.getWindow().getScaleFactor();
int centerX = client.getWindow().getScaledWidth() / 2; int centerX = client.getWindow().getScaledWidth() / 2;
@@ -87,11 +89,11 @@ public abstract class MouseMixin implements MouseAccessor {
if (action == 1) { if (action == 1) {
TouchInput.clickStartTime = System.currentTimeMillis(); TouchInput.clickStartTime = System.currentTimeMillis();
boolean bl = false; boolean bl = false;
if (client.currentScreen instanceof TouchscreenOverlay overlay) bl = overlay.mouseClicked(mouseX, mouseY, button); if (client.currentScreen instanceof TouchscreenOverlay overlay) bl = overlay.mouseClicked(new Click(mouseX, mouseY, input), false);
if (!bl) TouchInput.firstHitResult = TouchUtils.getTargetedObject(mouseX, mouseY); if (!bl) TouchInput.firstHitResult = TouchUtils.getTargetedObject(mouseX, mouseY);
if (client.currentScreen == null) ci.cancel(); if (client.currentScreen == null) ci.cancel();
} }
else if (TouchInput.mouseReleased(mouseX, mouseY, button)) ci.cancel(); else if (TouchInput.mouseReleased(mouseX, mouseY, input.button())) ci.cancel();
} }
} }
@@ -140,7 +142,7 @@ public abstract class MouseMixin implements MouseAccessor {
stack.getUseAction() == UseAction.SPEAR || stack.getItem() instanceof ThrowablePotionItem)); stack.getUseAction() == UseAction.SPEAR || stack.getItem() instanceof ThrowablePotionItem));
} }
@Inject(method = "lockCursor", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/util/InputUtil;setCursorParameters(JIDD)V",shift = At.Shift.BEFORE), cancellable = true) @Inject(method = "lockCursor", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/util/InputUtil;setCursorParameters(Lnet/minecraft/client/util/Window;IDD)V",shift = At.Shift.BEFORE), cancellable = true)
private void midnightcontrols$lockCursor(CallbackInfo ci) { private void midnightcontrols$lockCursor(CallbackInfo ci) {
if ((doMixedInput() || MidnightControlsConfig.eyeTrackerAsMouse)) { if ((doMixedInput() || MidnightControlsConfig.eyeTrackerAsMouse)) {
//In eye tracking mode, we cannot have the cursor locked to the center. //In eye tracking mode, we cannot have the cursor locked to the center.

View File

@@ -18,6 +18,7 @@ import eu.midnightdust.midnightcontrols.client.util.RainbowColor;
import net.minecraft.block.ShapeContext; import net.minecraft.block.ShapeContext;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.*; import net.minecraft.client.render.*;
import net.minecraft.client.render.state.WorldRenderState;
import net.minecraft.client.util.math.MatrixStack; import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.client.world.ClientWorld; import net.minecraft.client.world.ClientWorld;
import net.minecraft.item.BlockItem; import net.minecraft.item.BlockItem;
@@ -33,7 +34,6 @@ import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.awt.*; import java.awt.*;
@@ -54,31 +54,21 @@ public abstract class WorldRendererMixin {
@Shadow @Shadow
private ClientWorld world; private ClientWorld world;
@Shadow
@Final
private BufferBuilderStorage bufferBuilders;
@Redirect(method = "renderTargetBlockOutline", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/hit/BlockHitResult;getType()Lnet/minecraft/util/hit/HitResult$Type;"))
private HitResult.Type dontRenderOutline(BlockHitResult instance) {
if (MidnightControlsConfig.controlsMode == ControlsMode.TOUCHSCREEN && MidnightControlsConfig.touchMode == TouchMode.FINGER_POS) {
return HitResult.Type.MISS;
}
return instance.getType();
}
@Inject( @Inject(
method = "renderTargetBlockOutline", method = "renderTargetBlockOutline",
at = @At("HEAD") at = @At("HEAD"),
cancellable = true
) )
private void onOutlineRender(Camera camera, VertexConsumerProvider.Immediate vertexConsumers, MatrixStack matrices, boolean translucent, CallbackInfo ci) { private void onOutlineRender(VertexConsumerProvider.Immediate immediate, MatrixStack matrices, boolean renderBlockOutline, WorldRenderState renderStates, CallbackInfo ci) {
if (((MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER && MidnightControlsConfig.touchInControllerMode) || MidnightControlsConfig.controlsMode == ControlsMode.TOUCHSCREEN) if (((MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER && MidnightControlsConfig.touchInControllerMode) || MidnightControlsConfig.controlsMode == ControlsMode.TOUCHSCREEN)
&& MidnightControlsConfig.touchMode == TouchMode.FINGER_POS) { && MidnightControlsConfig.touchMode == TouchMode.FINGER_POS) {
this.midnightcontrols$renderFingerOutline(matrices, camera); this.midnightcontrols$renderFingerOutline(immediate, matrices, client.gameRenderer.getCamera());
ci.cancel();
} }
this.midnightcontrols$renderReacharoundOutline(matrices, camera); this.midnightcontrols$renderReacharoundOutline(immediate, matrices, client.gameRenderer.getCamera());
} }
@Unique @Unique
private void midnightcontrols$renderFingerOutline(MatrixStack matrices, Camera camera) { private void midnightcontrols$renderFingerOutline(VertexConsumerProvider.Immediate immediate, MatrixStack matrices, Camera camera) {
if (TouchInput.firstHitResult == null || TouchInput.firstHitResult.getType() != HitResult.Type.BLOCK) if (TouchInput.firstHitResult == null || TouchInput.firstHitResult.getType() != HitResult.Type.BLOCK)
return; return;
BlockHitResult result = (BlockHitResult) TouchInput.firstHitResult; BlockHitResult result = (BlockHitResult) TouchInput.firstHitResult;
@@ -89,14 +79,14 @@ public abstract class WorldRendererMixin {
if (MidnightControlsConfig.touchOutlineColorHex.isEmpty()) rgb = RainbowColor.radialRainbow(1,1); if (MidnightControlsConfig.touchOutlineColorHex.isEmpty()) rgb = RainbowColor.radialRainbow(1,1);
var pos = camera.getPos(); var pos = camera.getPos();
matrices.push(); matrices.push();
var vertexConsumer = this.bufferBuilders.getEntityVertexConsumers().getBuffer(RenderLayer.getLines()); var vertexConsumer = immediate.getBuffer(RenderLayer.getLines());
VertexRendering.drawOutline(matrices, vertexConsumer, outlineShape, blockPos.getX() - pos.getX(), blockPos.getY() - pos.getY(), blockPos.getZ() - pos.getZ(), VertexRendering.drawOutline(matrices, vertexConsumer, outlineShape, blockPos.getX() - pos.getX(), blockPos.getY() - pos.getY(), blockPos.getZ() - pos.getZ(),
ColorHelper.withAlpha(MidnightControlsConfig.touchOutlineColorAlpha, rgb.getRGB())); ColorHelper.withAlpha(MidnightControlsConfig.touchOutlineColorAlpha, rgb.getRGB()));
matrices.pop(); matrices.pop();
} }
} }
@Unique @Unique
private void midnightcontrols$renderReacharoundOutline(MatrixStack matrices, Camera camera) { private void midnightcontrols$renderReacharoundOutline(VertexConsumerProvider.Immediate immediate, MatrixStack matrices, Camera camera) {
if (this.client.crosshairTarget == null || this.client.crosshairTarget.getType() != HitResult.Type.MISS || !MidnightControlsConfig.shouldRenderReacharoundOutline) if (this.client.crosshairTarget == null || this.client.crosshairTarget.getType() != HitResult.Type.MISS || !MidnightControlsConfig.shouldRenderReacharoundOutline)
return; return;
var result = reacharound.getLastReacharoundResult(); var result = reacharound.getLastReacharoundResult();
@@ -121,7 +111,7 @@ public abstract class WorldRendererMixin {
Color rgb = MidnightColorUtil.hex2Rgb(MidnightControlsConfig.reacharoundOutlineColorHex); Color rgb = MidnightColorUtil.hex2Rgb(MidnightControlsConfig.reacharoundOutlineColorHex);
if (MidnightControlsConfig.reacharoundOutlineColorHex.isEmpty()) rgb = RainbowColor.radialRainbow(1,1); if (MidnightControlsConfig.reacharoundOutlineColorHex.isEmpty()) rgb = RainbowColor.radialRainbow(1,1);
matrices.push(); matrices.push();
var vertexConsumer = this.bufferBuilders.getEntityVertexConsumers().getBuffer(RenderLayer.getLines()); var vertexConsumer = immediate.getBuffer(RenderLayer.getLines());
VertexRendering.drawOutline(matrices, vertexConsumer, outlineShape, blockPos.getX() - pos.getX(), blockPos.getY() - pos.getY(), blockPos.getZ() - pos.getZ(), VertexRendering.drawOutline(matrices, vertexConsumer, outlineShape, blockPos.getX() - pos.getX(), blockPos.getY() - pos.getY(), blockPos.getZ() - pos.getZ(),
ColorHelper.withAlpha(MidnightControlsConfig.touchOutlineColorAlpha, rgb.getRGB())); ColorHelper.withAlpha(MidnightControlsConfig.touchOutlineColorAlpha, rgb.getRGB()));
matrices.pop(); matrices.pop();

View File

@@ -60,7 +60,7 @@ public class EyeTrackerHandler {
// The player entity's needs their facing rotated. // The player entity's needs their facing rotated.
double invertY = 1.0; double invertY = 1.0;
double moveMagnitude = Math.sqrt(normalizedX*normalizedX + normalizedY*normalizedY); double moveMagnitude = Math.sqrt(normalizedX*normalizedX + normalizedY*normalizedY);
if (client.options.getInvertYMouse().getValue()) { if (client.options.getInvertMouseY().getValue()) {
invertY = -1.0; invertY = -1.0;
} }
boolean notInDeadzone = (moveMagnitude > MidnightControlsConfig.eyeTrackerDeadzone) && !usingLongRangedTool; boolean notInDeadzone = (moveMagnitude > MidnightControlsConfig.eyeTrackerDeadzone) && !usingLongRangedTool;

View File

@@ -4,6 +4,9 @@ import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
import eu.midnightdust.midnightcontrols.client.touch.gui.TouchscreenOverlay; import eu.midnightdust.midnightcontrols.client.touch.gui.TouchscreenOverlay;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.Click;
import net.minecraft.client.input.MouseInput;
import net.minecraft.client.particle.BlockDustParticle;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.util.ActionResult; import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand; import net.minecraft.util.Hand;
@@ -46,7 +49,7 @@ public class TouchInput {
if (result instanceof BlockHitResult blockHit && firstHitResult instanceof BlockHitResult firstBlock && blockHit.getBlockPos().equals(firstBlock.getBlockPos())) { if (result instanceof BlockHitResult blockHit && firstHitResult instanceof BlockHitResult firstBlock && blockHit.getBlockPos().equals(firstBlock.getBlockPos())) {
if (MidnightControlsConfig.debug) System.out.println(blockHit.getBlockPos().toString()); if (MidnightControlsConfig.debug) System.out.println(blockHit.getBlockPos().toString());
if (client.interactionManager.updateBlockBreakingProgress(blockHit.getBlockPos(), blockHit.getSide())) { if (client.interactionManager.updateBlockBreakingProgress(blockHit.getBlockPos(), blockHit.getSide())) {
client.particleManager.addBlockBreakingParticles(blockHit.getBlockPos(), blockHit.getSide()); //client.particleManager.addBlockBreakingParticles(blockHit.getBlockPos(), blockHit.getSide()); // TODO Re-implement block breaking particles!!!
client.player.swingHand(Hand.MAIN_HAND); client.player.swingHand(Hand.MAIN_HAND);
} else client.interactionManager.cancelBlockBreaking(); } else client.interactionManager.cancelBlockBreaking();
firstHitResult = TouchUtils.getTargetedObject(mouseX, mouseY); firstHitResult = TouchUtils.getTargetedObject(mouseX, mouseY);
@@ -62,7 +65,7 @@ public class TouchInput {
isDragging = false; isDragging = false;
firstHitResult = null; firstHitResult = null;
if (client.interactionManager != null) client.interactionManager.cancelBlockBreaking(); if (client.interactionManager != null) client.interactionManager.cancelBlockBreaking();
if ((client.currentScreen == null || !client.currentScreen.mouseReleased(mouseX, mouseY, button)) && System.currentTimeMillis() - clickStartTime < MidnightControlsConfig.touchBreakDelay) { if ((client.currentScreen == null || !client.currentScreen.mouseReleased(new Click(mouseX, mouseY, new MouseInput(button, 0)))) && System.currentTimeMillis() - clickStartTime < MidnightControlsConfig.touchBreakDelay) {
assert client.player != null; assert client.player != null;
assert client.world != null; assert client.world != null;
assert client.interactionManager != null; assert client.interactionManager != null;

View File

@@ -34,13 +34,13 @@ public class TouchUtils {
Vec3d far = screenSpaceToWorldSpace(mouseX, mouseY, 1); Vec3d far = screenSpaceToWorldSpace(mouseX, mouseY, 1);
float playerRange = getPlayerRange(client); float playerRange = getPlayerRange(client);
EntityHitResult entityCast = ProjectileUtil.raycast(client.player, near, far, Box.from(client.player.getPos()).expand(playerRange), entity -> (!entity.isSpectator() && entity.isAttackable()), playerRange * playerRange); EntityHitResult entityCast = ProjectileUtil.raycast(client.player, near, far, Box.from(client.player.getEntityPos()).expand(playerRange), entity -> (!entity.isSpectator() && entity.isAttackable()), playerRange * playerRange);
if (entityCast != null && entityCast.getType() == HitResult.Type.ENTITY) return entityCast; if (entityCast != null && entityCast.getType() == HitResult.Type.ENTITY) return entityCast;
BlockHitResult result = client.world.raycast(new RaycastContext(near, far, RaycastContext.ShapeType.OUTLINE, RaycastContext.FluidHandling.NONE, client.player)); BlockHitResult result = client.world.raycast(new RaycastContext(near, far, RaycastContext.ShapeType.OUTLINE, RaycastContext.FluidHandling.NONE, client.player));
if (client.player.getPos().distanceTo(result.getPos()) > playerRange) return null; if (client.player.getEntityPos().distanceTo(result.getPos()) > playerRange) return null;
return result; return result;
} }

View File

@@ -11,12 +11,15 @@ package eu.midnightdust.midnightcontrols.client.touch.gui;
import eu.midnightdust.midnightcontrols.client.touch.TouchInput; import eu.midnightdust.midnightcontrols.client.touch.TouchInput;
import eu.midnightdust.midnightcontrols.client.util.storage.AxisStorage; import eu.midnightdust.midnightcontrols.client.util.storage.AxisStorage;
import net.minecraft.client.gui.Click;
import net.minecraft.client.gui.screen.ChatScreen; import net.minecraft.client.gui.screen.ChatScreen;
import net.minecraft.client.gui.screen.GameMenuScreen; import net.minecraft.client.gui.screen.GameMenuScreen;
import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.util.SpriteIdentifier;
import net.minecraft.component.DataComponentTypes; import net.minecraft.component.DataComponentTypes;
import net.minecraft.item.consume.UseAction; import net.minecraft.item.consume.UseAction;
import net.minecraft.util.Arm; import net.minecraft.util.Arm;
import net.minecraft.util.Atlases;
import net.minecraft.util.Hand; import net.minecraft.util.Hand;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import org.thinkingstudio.obsidianui.Position; import org.thinkingstudio.obsidianui.Position;
@@ -170,7 +173,7 @@ public class TouchscreenOverlay extends Screen {
this.addDrawableChild(emoteButton); this.addDrawableChild(emoteButton);
} }
TextIconButtonWidget chatButton = TextIconButtonWidget.builder(Text.empty(), btn -> this.client.setScreen(new ChatScreen("")), true).width(20).texture(id("touch/chat"), 20, 20).build(); TextIconButtonWidget chatButton = TextIconButtonWidget.builder(Text.empty(), btn -> this.client.setScreen(new ChatScreen("", true)), true).width(20).texture(id("touch/chat"), 20, 20).build();
chatButton.setPosition(scaledWidth / 2 - 20 + emoteOffset, 0); chatButton.setPosition(scaledWidth / 2 - 20 + emoteOffset, 0);
this.addDrawableChild(chatButton); this.addDrawableChild(chatButton);
TextIconButtonWidget pauseButton = TextIconButtonWidget.builder(Text.empty(), btn -> this.pauseGame(), true).width(20).texture(id("touch/pause"), 20, 20).build(); TextIconButtonWidget pauseButton = TextIconButtonWidget.builder(Text.empty(), btn -> this.pauseGame(), true).width(20).texture(id("touch/pause"), 20, 20).build();
@@ -289,12 +292,12 @@ public class TouchscreenOverlay extends Screen {
assert client != null; assert client != null;
Identifier emptySprite = id("touch/empty"); Identifier emptySprite = id("touch/empty");
List<String> list = left ? MidnightControlsConfig.leftTouchBinds : MidnightControlsConfig.rightTouchBinds; List<String> list = left ? MidnightControlsConfig.leftTouchBinds : MidnightControlsConfig.rightTouchBinds;
Sprite missingSprite = client.getGuiAtlasManager().getSprite(MissingSprite.getMissingSpriteId()); Sprite missingSprite = client.getAtlasManager().getAtlasTexture(Atlases.GUI).getMissingSprite();
for (int i = 0; i < list.size(); i++) { for (int i = 0; i < list.size(); i++) {
String bindName = list.get(i); String bindName = list.get(i);
ButtonBinding binding = InputManager.getBinding(bindName); ButtonBinding binding = InputManager.getBinding(bindName);
if (binding == null) continue; if (binding == null) continue;
boolean hasTexture = client.getGuiAtlasManager().getSprite(id("binding/"+bindName)) != missingSprite; boolean hasTexture = client.getAtlasManager().getAtlasTexture(Atlases.GUI).getSprite(id("binding/"+bindName)) != missingSprite;
if (MidnightControlsConfig.debug) System.out.println(left +" "+id("binding/"+bindName)+" "+ hasTexture); if (MidnightControlsConfig.debug) System.out.println(left +" "+id("binding/"+bindName)+" "+ hasTexture);
var button = TextIconButtonWidget.builder(Text.translatable(binding.getTranslationKey()), b -> { var button = TextIconButtonWidget.builder(Text.translatable(binding.getTranslationKey()), b -> {
binding.handle(client, 1.0f, ButtonState.PRESS); binding.handle(client, 1.0f, ButtonState.PRESS);
@@ -349,8 +352,8 @@ public class TouchscreenOverlay extends Screen {
} }
@Override @Override
public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) { public boolean mouseDragged(Click click, double deltaX, double deltaY) {
if (button == GLFW.GLFW_MOUSE_BUTTON_1 && this.client != null) { if (click.button() == GLFW.GLFW_MOUSE_BUTTON_1 && this.client != null) {
if (TouchInput.isDragging) { if (TouchInput.isDragging) {
if (!MidnightControlsConfig.invertTouch) { if (!MidnightControlsConfig.invertTouch) {
deltaX = -deltaX; deltaX = -deltaX;
@@ -361,6 +364,6 @@ public class TouchscreenOverlay extends Screen {
} }
else TouchInput.isDragging = true; else TouchInput.isDragging = true;
} }
return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY); return super.mouseDragged(click, deltaX, deltaY);
} }
} }

View File

@@ -40,7 +40,7 @@ public interface HandledScreenAccessor {
*/ */
Slot midnightcontrols$getSlotAt(double posX, double posY); Slot midnightcontrols$getSlotAt(double posX, double posY);
boolean midnightcontrols$isClickOutsideBounds(double mouseX, double mouseY, int x, int y, int button); boolean midnightcontrols$isClickOutsideBounds(double mouseX, double mouseY, int left, int top);
/** /**
* Handles a mouse click on the specified slot. * Handles a mouse click on the specified slot.

View File

@@ -1,6 +1,7 @@
package eu.midnightdust.midnightcontrols.client.util.platform; package eu.midnightdust.midnightcontrols.client.util.platform;
import dev.architectury.injectables.annotations.ExpectPlatform; import dev.architectury.injectables.annotations.ExpectPlatform;
import eu.midnightdust.midnightcontrols.client.MidnightInput;
import eu.midnightdust.midnightcontrols.client.mixin.CreativeInventoryScreenAccessor; import eu.midnightdust.midnightcontrols.client.mixin.CreativeInventoryScreenAccessor;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen; import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen;
@@ -11,6 +12,8 @@ import org.jetbrains.annotations.NotNull;
import java.util.List; import java.util.List;
import static eu.midnightdust.midnightcontrols.client.MidnightInput.ENTER_KEY_INPUT;
public class ItemGroupUtil { public class ItemGroupUtil {
@ExpectPlatform @ExpectPlatform
public static List<ItemGroup> getVisibleGroups(CreativeInventoryScreen screen) { public static List<ItemGroup> getVisibleGroups(CreativeInventoryScreen screen) {
@@ -24,10 +27,10 @@ public class ItemGroupUtil {
.filter(element -> element.getMessage() != null && element.getMessage().getContent() != null) .filter(element -> element.getMessage() != null && element.getMessage().getContent() != null)
.anyMatch(element -> { .anyMatch(element -> {
if (next && element.getMessage().getString().equals(">")) { if (next && element.getMessage().getString().equals(">")) {
element.onPress(); element.onPress(ENTER_KEY_INPUT);
return true; return true;
} else if (element.getMessage().getString().equals("<")) { } else if (element.getMessage().getString().equals("<")) {
element.onPress(); element.onPress(ENTER_KEY_INPUT);
return true; return true;
} }
return false; return false;

View File

@@ -4,6 +4,7 @@ import eu.midnightdust.midnightcontrols.client.virtualkeyboard.clickhandler.Abst
import eu.midnightdust.midnightcontrols.client.virtualkeyboard.clickhandler.BookEditScreenClickHandler; import eu.midnightdust.midnightcontrols.client.virtualkeyboard.clickhandler.BookEditScreenClickHandler;
import eu.midnightdust.midnightcontrols.client.virtualkeyboard.clickhandler.DefaultScreenClickHandler; import eu.midnightdust.midnightcontrols.client.virtualkeyboard.clickhandler.DefaultScreenClickHandler;
import eu.midnightdust.midnightcontrols.client.virtualkeyboard.clickhandler.SignEditScreenClickHandler; import eu.midnightdust.midnightcontrols.client.virtualkeyboard.clickhandler.SignEditScreenClickHandler;
import net.minecraft.client.gui.Click;
import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.screen.ingame.BookEditScreen; import net.minecraft.client.gui.screen.ingame.BookEditScreen;
import net.minecraft.client.gui.screen.ingame.BookSigningScreen; import net.minecraft.client.gui.screen.ingame.BookSigningScreen;
@@ -26,13 +27,13 @@ public class MouseClickInterceptor {
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <T extends Screen> void intercept(T screen, double mouseX, double mouseY) { public <T extends Screen> void intercept(T screen, Click click) {
AbstractScreenClickHandler<T> handler = (AbstractScreenClickHandler<T>) clickHandlers.get(screen.getClass()); AbstractScreenClickHandler<T> handler = (AbstractScreenClickHandler<T>) clickHandlers.get(screen.getClass());
if (handler == null) { if (handler == null) {
handler = (AbstractScreenClickHandler<T>) clickHandlers.get(Screen.class); handler = (AbstractScreenClickHandler<T>) clickHandlers.get(Screen.class);
} }
handler.handle(screen, mouseX, mouseY); handler.handle(screen, click.x(), click.y());
} }
} }

View File

@@ -14,6 +14,7 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.client; import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.client;
import static eu.midnightdust.midnightcontrols.client.MidnightInput.ENTER_KEY_INPUT;
public class DefaultScreenClickHandler extends AbstractScreenClickHandler<Screen> { public class DefaultScreenClickHandler extends AbstractScreenClickHandler<Screen> {
@@ -54,7 +55,7 @@ public class DefaultScreenClickHandler extends AbstractScreenClickHandler<Screen
} }
case ChatScreen chatScreen -> { case ChatScreen chatScreen -> {
// send the chat message // send the chat message
chatScreen.keyPressed(GLFW.GLFW_KEY_ENTER, 0, 0); chatScreen.keyPressed(ENTER_KEY_INPUT);
} }
default -> { default -> {
} }

View File

@@ -1,5 +1,5 @@
{ {
"midnightcontrols.midnightconfig.title": "MidnightControls Advanced Config", "midnightcontrols.midnightconfig.title": "MidnightControls Config",
"midnightcontrols.midnightconfig.enum.VirtualMouseSkin.DEFAULT_LIGHT": "Default Light", "midnightcontrols.midnightconfig.enum.VirtualMouseSkin.DEFAULT_LIGHT": "Default Light",
"midnightcontrols.midnightconfig.enum.VirtualMouseSkin.DEFAULT_DARK": "Default Dark", "midnightcontrols.midnightconfig.enum.VirtualMouseSkin.DEFAULT_DARK": "Default Dark",
"midnightcontrols.midnightconfig.enum.VirtualMouseSkin.SECOND_LIGHT": "Second Light", "midnightcontrols.midnightconfig.enum.VirtualMouseSkin.SECOND_LIGHT": "Second Light",
@@ -23,7 +23,7 @@
"midnightcontrols.midnightconfig.enum.TouchMode.FINGER_POS": "Finger Position", "midnightcontrols.midnightconfig.enum.TouchMode.FINGER_POS": "Finger Position",
"midnightcontrols.midnightconfig.enum.CameraMode.FLAT": "Flat", "midnightcontrols.midnightconfig.enum.CameraMode.FLAT": "Flat",
"midnightcontrols.midnightconfig.enum.CameraMode.ADAPTIVE": "Adaptive", "midnightcontrols.midnightconfig.enum.CameraMode.ADAPTIVE": "Adaptive",
"key.categories.midnightcontrols": "MidnightControls", "key.category.midnightcontrols.keybinds": "MidnightControls",
"key.midnightcontrols.look_down": "Look Down", "key.midnightcontrols.look_down": "Look Down",
"key.midnightcontrols.look_left": "Look Left", "key.midnightcontrols.look_left": "Look Left",
"key.midnightcontrols.look_right": "Look Right", "key.midnightcontrols.look_right": "Look Right",
@@ -237,6 +237,7 @@
"midnightcontrols.virtual_mouse.skin.second_light": "Second Light", "midnightcontrols.virtual_mouse.skin.second_light": "Second Light",
"midnightcontrols.virtual_mouse.skin.second_dark": "Second Dark", "midnightcontrols.virtual_mouse.skin.second_dark": "Second Dark",
"midnightcontrols.midnightconfig.category.controller": "Controller", "midnightcontrols.midnightconfig.category.controller": "Controller",
"midnightcontrols.midnightconfig.category.buttons": "Buttons",
"midnightcontrols.midnightconfig.category.misc": "Miscellaneous", "midnightcontrols.midnightconfig.category.misc": "Miscellaneous",
"midnightcontrols.midnightconfig.category.screens": "Screens", "midnightcontrols.midnightconfig.category.screens": "Screens",
"midnightcontrols.midnightconfig.category.gameplay": "Gameplay", "midnightcontrols.midnightconfig.category.gameplay": "Gameplay",

Binary file not shown.

After

Width:  |  Height:  |  Size: 311 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 298 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 341 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 312 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 296 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 335 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 339 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 266 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 260 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 261 B

View File

@@ -12,6 +12,7 @@
"ClickableWidgetAccessor", "ClickableWidgetAccessor",
"ClientPlayerEntityMixin", "ClientPlayerEntityMixin",
"CreativeInventoryScreenAccessor", "CreativeInventoryScreenAccessor",
"CursorMixin",
"DrawContextAccessor", "DrawContextAccessor",
"GameOptionsScreenMixin", "GameOptionsScreenMixin",
"GameRendererMixin", "GameRendererMixin",
@@ -20,6 +21,7 @@
"InputUtilMixin", "InputUtilMixin",
"KeyBindingIDAccessor", "KeyBindingIDAccessor",
"KeyBindingMixin", "KeyBindingMixin",
"KeyboardAccessor",
"KeyboardMixin", "KeyboardMixin",
"MinecraftClientMixin", "MinecraftClientMixin",
"MouseAccessor", "MouseAccessor",

View File

@@ -1,6 +1,7 @@
package eu.midnightdust.midnightcontrols.fabric.event; package eu.midnightdust.midnightcontrols.fabric.event;
import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig; import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
import net.fabricmc.fabric.api.client.screen.v1.ScreenMouseEvents; import net.fabricmc.fabric.api.client.screen.v1.ScreenMouseEvents;
import net.minecraft.client.gui.Click;
import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.Screen;
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.clickInterceptor; import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.clickInterceptor;
@@ -13,9 +14,9 @@ public class MouseClickListener implements ScreenMouseEvents.AllowMouseClick {
} }
@Override @Override
public boolean allowMouseClick(Screen screen, double mouseX, double mouseY, int button) { public boolean allowMouseClick(Screen screen, Click click) {
if(MidnightControlsConfig.virtualKeyboard) { if(MidnightControlsConfig.virtualKeyboard) {
clickInterceptor.intercept(screen, mouseX, mouseY); clickInterceptor.intercept(screen, click);
} }
return true; return true;
} }
@@ -33,8 +34,4 @@ public class MouseClickListener implements ScreenMouseEvents.AllowMouseClick {
public int hashCode() { public int hashCode() {
return screen.hashCode(); return screen.hashCode();
} }
} }

View File

@@ -52,7 +52,7 @@
"depends": { "depends": {
"fabricloader": ">=0.11.3", "fabricloader": ">=0.11.3",
"fabric": ">=0.71.0", "fabric": ">=0.71.0",
"minecraft": ">=1.20.5", "minecraft": ">=1.21.9",
"obsidianui": ">=0.2.5", "obsidianui": ">=0.2.5",
"java": ">=21" "java": ">=21"
}, },

View File

@@ -2,25 +2,25 @@
org.gradle.parallel=true org.gradle.parallel=true
org.gradle.jvmargs=-Xmx2048M org.gradle.jvmargs=-Xmx2048M
minecraft_version=1.21.6 minecraft_version=1.21.9
supported_versions=1.21.8 supported_versions=
yarn_mappings=1.21.6+build.1 yarn_mappings=1.21.9+build.1
enabled_platforms=fabric,neoforge enabled_platforms=fabric,neoforge
archives_base_name=midnightcontrols archives_base_name=midnightcontrols
mod_version=1.11.2 mod_version=1.11.3-beta.1
maven_group=eu.midnightdust maven_group=eu.midnightdust
release_type=release release_type=alpha
modrinth_id = bXX9h73M modrinth_id = bXX9h73M
curseforge_id = 621768 curseforge_id = 621768
# Configure the IDs here after creating the projects on the websites # Configure the IDs here after creating the projects on the websites
midnightlib_version=1.7.5+1.21.6 midnightlib_version=1.8.2+1.21.9
fabric_loader_version=0.16.14 fabric_loader_version=0.17.2
fabric_api_version=0.127.0+1.21.6 fabric_api_version=0.133.13+1.21.9
neoforge_version=21.6.0-beta neoforge_version=21.9.3-beta
yarn_mappings_patch_neoforge_version = 1.21+build.4 yarn_mappings_patch_neoforge_version = 1.21+build.4
quilt_loader_version=0.19.0-beta.18 quilt_loader_version=0.19.0-beta.18

View File

@@ -10,6 +10,6 @@ pluginManagement {
include("common") include("common")
include("fabric") include("fabric")
//include("quilt") // Native quilt support is disabled atm, as the Quilt libraries are currently in maintenance mode //include("quilt") // Native quilt support is disabled atm, as the Quilt libraries are currently in maintenance mode
include("neoforge") //include("neoforge")
rootProject.name = "midnightcontrols" rootProject.name = "midnightcontrols"