mirror of
https://github.com/TeamMidnightDust/MidnightControls.git
synced 2025-12-14 07:35:10 +01:00
Implement NeoForge support
This commit is contained in:
@@ -26,6 +26,7 @@ import eu.midnightdust.midnightcontrols.client.mixin.KeyBindingIDAccessor;
|
|||||||
import eu.midnightdust.midnightcontrols.client.ring.ButtonBindingRingAction;
|
import eu.midnightdust.midnightcontrols.client.ring.ButtonBindingRingAction;
|
||||||
import eu.midnightdust.midnightcontrols.client.ring.MidnightRing;
|
import eu.midnightdust.midnightcontrols.client.ring.MidnightRing;
|
||||||
import eu.midnightdust.midnightcontrols.client.util.platform.NetworkUtil;
|
import eu.midnightdust.midnightcontrols.client.util.platform.NetworkUtil;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.virtualkeyboard.MouseClickInterceptor;
|
||||||
import net.minecraft.client.gui.screen.Screen;
|
import net.minecraft.client.gui.screen.Screen;
|
||||||
import org.thinkingstudio.obsidianui.hud.HudManager;
|
import org.thinkingstudio.obsidianui.hud.HudManager;
|
||||||
import eu.midnightdust.midnightcontrols.client.touch.TouchInput;
|
import eu.midnightdust.midnightcontrols.client.touch.TouchInput;
|
||||||
@@ -75,6 +76,7 @@ public class MidnightControlsClient extends MidnightControls {
|
|||||||
public static final MidnightInput input = new MidnightInput();
|
public static final MidnightInput input = new MidnightInput();
|
||||||
public static final MidnightRing ring = new MidnightRing();
|
public static final MidnightRing ring = new MidnightRing();
|
||||||
public static final MidnightReacharound reacharound = new MidnightReacharound();
|
public static final MidnightReacharound reacharound = new MidnightReacharound();
|
||||||
|
public static final MouseClickInterceptor clickInterceptor = new MouseClickInterceptor();
|
||||||
public static boolean isWayland;
|
public static boolean isWayland;
|
||||||
private static MidnightControlsHud hud;
|
private static MidnightControlsHud hud;
|
||||||
private static ControlsMode previousControlsMode;
|
private static ControlsMode previousControlsMode;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package eu.midnightdust.midnightcontrols.client.gui.virtualkeyboard;
|
package eu.midnightdust.midnightcontrols.client.virtualkeyboard;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package eu.midnightdust.midnightcontrols.client.virtualkeyboard;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.virtualkeyboard.clickhandler.AbstractScreenClickHandler;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.virtualkeyboard.clickhandler.BookEditScreenClickHandler;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.virtualkeyboard.clickhandler.DefaultScreenClickHandler;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.virtualkeyboard.clickhandler.SignEditScreenHandler;
|
||||||
|
import net.minecraft.client.gui.screen.Screen;
|
||||||
|
import net.minecraft.client.gui.screen.ingame.BookEditScreen;
|
||||||
|
import net.minecraft.client.gui.screen.ingame.SignEditScreen;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
||||||
|
public class MouseClickInterceptor {
|
||||||
|
|
||||||
|
private final Map<Class<?>, AbstractScreenClickHandler<?>> clickHandlers;
|
||||||
|
|
||||||
|
public MouseClickInterceptor() {
|
||||||
|
this.clickHandlers = new HashMap<>();
|
||||||
|
this.clickHandlers.put(BookEditScreen.class, new BookEditScreenClickHandler());
|
||||||
|
this.clickHandlers.put(SignEditScreen.class, new SignEditScreenHandler());
|
||||||
|
this.clickHandlers.put(Screen.class, new DefaultScreenClickHandler());
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public <T extends Screen> void intercept(T screen, double mouseX, double mouseY) {
|
||||||
|
AbstractScreenClickHandler<T> handler = (AbstractScreenClickHandler<T>) clickHandlers.get(screen.getClass());
|
||||||
|
|
||||||
|
if (handler == null) {
|
||||||
|
handler = (AbstractScreenClickHandler<T>) clickHandlers.get(Screen.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
handler.handle(screen, mouseX, mouseY);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package eu.midnightdust.midnightcontrols.client.virtualkeyboard.clickhandler;
|
||||||
|
|
||||||
|
import net.minecraft.client.gui.screen.Screen;
|
||||||
|
|
||||||
|
public abstract class AbstractScreenClickHandler<T extends Screen> {
|
||||||
|
public abstract void handle(T screen, double mouseX, double mouseY);
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package eu.midnightdust.midnightcontrols.client.virtualkeyboard.clickhandler;
|
||||||
|
|
||||||
|
import eu.midnightdust.midnightcontrols.client.mixin.BookEditScreenAccessor;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.virtualkeyboard.gui.VirtualKeyboardScreen;
|
||||||
|
import net.minecraft.client.gui.screen.ingame.BookEditScreen;
|
||||||
|
|
||||||
|
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.client;
|
||||||
|
|
||||||
|
public class BookEditScreenClickHandler extends AbstractScreenClickHandler<BookEditScreen> {
|
||||||
|
@Override
|
||||||
|
public void handle(BookEditScreen screen, double mouseX, double mouseY) {
|
||||||
|
// don't open the keyboard if a UI element was clicked
|
||||||
|
if(screen.hoveredElement(mouseX, mouseY).isPresent()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var accessor = (BookEditScreenAccessor) screen;
|
||||||
|
|
||||||
|
VirtualKeyboardScreen virtualKeyboardScreen;
|
||||||
|
if(accessor.midnightcontrols$isSigning()) {
|
||||||
|
virtualKeyboardScreen = new VirtualKeyboardScreen(accessor.midnightcontrols$getTitle(), (text) -> {
|
||||||
|
client.setScreen(screen);
|
||||||
|
accessor.midnightcontrols$setTitle(text);
|
||||||
|
}, true);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
virtualKeyboardScreen = new VirtualKeyboardScreen(accessor.midnightcontrols$getCurrentPageContent(), (text) -> {
|
||||||
|
client.setScreen(screen);
|
||||||
|
accessor.midnightcontrols$setPageContent(text);
|
||||||
|
accessor.midnightcontrols$getCurrentPageSelectionManager().putCursorAtEnd();
|
||||||
|
}, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
client.setScreen(virtualKeyboardScreen);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,137 @@
|
|||||||
|
package eu.midnightdust.midnightcontrols.client.virtualkeyboard.clickhandler;
|
||||||
|
|
||||||
|
import eu.midnightdust.midnightcontrols.client.mixin.CreativeInventoryScreenAccessor;
|
||||||
|
import eu.midnightdust.midnightcontrols.client.virtualkeyboard.gui.VirtualKeyboardScreen;
|
||||||
|
import net.minecraft.client.gui.Element;
|
||||||
|
import net.minecraft.client.gui.ParentElement;
|
||||||
|
import net.minecraft.client.gui.screen.ChatScreen;
|
||||||
|
import net.minecraft.client.gui.screen.Screen;
|
||||||
|
import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen;
|
||||||
|
import net.minecraft.client.gui.widget.TextFieldWidget;
|
||||||
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.client;
|
||||||
|
|
||||||
|
public class DefaultScreenClickHandler extends AbstractScreenClickHandler<Screen> {
|
||||||
|
|
||||||
|
private Screen parentScreen;
|
||||||
|
private List<Integer> textFieldElementPath;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(Screen screen, double mouseX, double mouseY) {
|
||||||
|
var textField = findClickedTextField(screen, mouseX, mouseY);
|
||||||
|
if (textField == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.parentScreen = screen;
|
||||||
|
this.textFieldElementPath = calculatePathToElement(screen, textField);
|
||||||
|
|
||||||
|
var virtualKeyboardScreen = new VirtualKeyboardScreen(textField.getText(), this::handleKeyboardClose, false);
|
||||||
|
client.setScreen(virtualKeyboardScreen);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleKeyboardClose(String newText) {
|
||||||
|
if(this.parentScreen == null || this.textFieldElementPath == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
client.setScreen(this.parentScreen);
|
||||||
|
TextFieldWidget textField = findTextFieldByPath(this.parentScreen, this.textFieldElementPath);
|
||||||
|
if (textField == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
textField.setText(newText);
|
||||||
|
|
||||||
|
switch (this.parentScreen) {
|
||||||
|
case CreativeInventoryScreen creativeInventoryScreen -> {
|
||||||
|
var accessor = (CreativeInventoryScreenAccessor) creativeInventoryScreen;
|
||||||
|
accessor.midnightcontrols$search();
|
||||||
|
}
|
||||||
|
case ChatScreen chatScreen -> {
|
||||||
|
// send the chat message
|
||||||
|
chatScreen.keyPressed(GLFW.GLFW_KEY_ENTER, 0, 0);
|
||||||
|
}
|
||||||
|
default -> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private TextFieldWidget findClickedTextField(Screen screen, double mouseX, double mouseY) {
|
||||||
|
for (Element element : screen.children()) {
|
||||||
|
if (element instanceof TextFieldWidget textField) {
|
||||||
|
if (textField.isMouseOver(mouseX, mouseY) && textField.isFocused()) {
|
||||||
|
return textField;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// not hovering over a text field
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the path between a parent and a target in the UI hierarchy
|
||||||
|
*/
|
||||||
|
protected List<Integer> calculatePathToElement(Element parent, Element target) {
|
||||||
|
if (parent instanceof ParentElement parentElement) {
|
||||||
|
List<? extends Element> children = parentElement.children();
|
||||||
|
|
||||||
|
// check direct children first
|
||||||
|
for (int i = 0; i < children.size(); i++) {
|
||||||
|
if (children.get(i) == target) {
|
||||||
|
// found it, return the path to this element
|
||||||
|
return Collections.singletonList(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check each child's children
|
||||||
|
for (int i = 0; i < children.size(); i++) {
|
||||||
|
if (children.get(i) instanceof ParentElement childParent) {
|
||||||
|
List<Integer> subPath = calculatePathToElement(childParent, target);
|
||||||
|
if (subPath != null) {
|
||||||
|
// found in this subtree, prepend current index
|
||||||
|
List<Integer> fullPath = new ArrayList<>();
|
||||||
|
fullPath.add(i);
|
||||||
|
fullPath.addAll(subPath);
|
||||||
|
return fullPath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not found
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected TextFieldWidget findTextFieldByPath(Element parent, List<Integer> path) {
|
||||||
|
if (path == null || path.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parent instanceof ParentElement parentElement) {
|
||||||
|
List<? extends Element> children = parentElement.children();
|
||||||
|
int index = path.getFirst();
|
||||||
|
|
||||||
|
if (index >= 0 && index < children.size()) {
|
||||||
|
Element child = children.get(index);
|
||||||
|
|
||||||
|
if (path.size() == 1) {
|
||||||
|
// This should be our target
|
||||||
|
return (child instanceof TextFieldWidget) ? (TextFieldWidget) child : null;
|
||||||
|
} else {
|
||||||
|
// Continue traversing
|
||||||
|
if (child instanceof ParentElement) {
|
||||||
|
return findTextFieldByPath(child, path.subList(1, path.size()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package eu.midnightdust.midnightcontrols.client.virtualkeyboard.clickhandler;
|
||||||
|
|
||||||
|
import eu.midnightdust.midnightcontrols.client.mixin.AbstractSignEditScreenAccessor;
|
||||||
|
import net.minecraft.client.gui.screen.ingame.SignEditScreen;
|
||||||
|
|
||||||
|
public class SignEditScreenHandler extends AbstractScreenClickHandler<SignEditScreen> {
|
||||||
|
@Override
|
||||||
|
public void handle(SignEditScreen screen, double mouseX, double mouseY) {
|
||||||
|
// don't open the keyboard if a UI element was clicked
|
||||||
|
if(screen.hoveredElement(mouseX, mouseY).isPresent()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var accessor = (AbstractSignEditScreenAccessor) screen;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
package eu.midnightdust.midnightcontrols.client.gui.virtualkeyboard;
|
package eu.midnightdust.midnightcontrols.client.virtualkeyboard.gui;
|
||||||
|
|
||||||
|
import eu.midnightdust.midnightcontrols.client.virtualkeyboard.KeyboardLayout;
|
||||||
import net.minecraft.client.gui.DrawContext;
|
import net.minecraft.client.gui.DrawContext;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
import org.thinkingstudio.obsidianui.Position;
|
import org.thinkingstudio.obsidianui.Position;
|
||||||
@@ -1,68 +1,22 @@
|
|||||||
package eu.midnightdust.midnightcontrols.fabric.event;
|
package eu.midnightdust.midnightcontrols.fabric.event;
|
||||||
import eu.midnightdust.midnightcontrols.client.gui.virtualkeyboard.VirtualKeyboardScreen;
|
|
||||||
import eu.midnightdust.midnightcontrols.client.mixin.AbstractSignEditScreenAccessor;
|
|
||||||
import eu.midnightdust.midnightcontrols.client.mixin.BookEditScreenAccessor;
|
|
||||||
import eu.midnightdust.midnightcontrols.client.mixin.CreativeInventoryScreenAccessor;
|
|
||||||
import net.fabricmc.fabric.api.client.screen.v1.ScreenMouseEvents;
|
import net.fabricmc.fabric.api.client.screen.v1.ScreenMouseEvents;
|
||||||
import net.minecraft.client.gui.Element;
|
|
||||||
import net.minecraft.client.gui.ParentElement;
|
|
||||||
import net.minecraft.client.gui.screen.ChatScreen;
|
|
||||||
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.CreativeInventoryScreen;
|
|
||||||
import net.minecraft.client.gui.screen.ingame.SignEditScreen;
|
|
||||||
import net.minecraft.client.gui.widget.TextFieldWidget;
|
|
||||||
import org.lwjgl.glfw.GLFW;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.clickInterceptor;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import static eu.midnightdust.midnightcontrols.MidnightControls.logger;
|
|
||||||
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.client;
|
|
||||||
|
|
||||||
record ScreenLink(Screen screen, List<Integer> elementPath) {}
|
|
||||||
|
|
||||||
public class MouseClickListener implements ScreenMouseEvents.AllowMouseClick {
|
public class MouseClickListener implements ScreenMouseEvents.AllowMouseClick {
|
||||||
private final Screen screen;
|
private final Screen screen;
|
||||||
|
|
||||||
private ScreenLink link;
|
|
||||||
|
|
||||||
public MouseClickListener(Screen screen) {
|
public MouseClickListener(Screen screen) {
|
||||||
this.screen = screen;
|
this.screen = screen;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean allowMouseClick(Screen screen, double mouseX, double mouseY, int button) {
|
public boolean allowMouseClick(Screen screen, double mouseX, double mouseY, int button) {
|
||||||
interceptMouseClick(screen, mouseX, mouseY);
|
clickInterceptor.intercept(screen, mouseX, mouseY);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void interceptMouseClick(Screen screen, double mouseX, double mouseY) {
|
|
||||||
logger.info("In scr: {}", screen.getClass());
|
|
||||||
switch(screen) {
|
|
||||||
case BookEditScreen bookEditScreen -> {
|
|
||||||
if(screen.hoveredElement(mouseX, mouseY).isPresent()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
handleBookEditScreenClick(bookEditScreen);
|
|
||||||
}
|
|
||||||
case SignEditScreen signEditScreen -> {
|
|
||||||
if(screen.hoveredElement(mouseX, mouseY).isPresent()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
handleSignEditScreenClick(signEditScreen);
|
|
||||||
}
|
|
||||||
default -> {
|
|
||||||
var textField = findClickedTextField(screen, mouseX, mouseY);
|
|
||||||
if (textField == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
handleTextFieldClick(textField);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add equals and hashCode to prevent duplicate registrations
|
// Add equals and hashCode to prevent duplicate registrations
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
@@ -77,139 +31,7 @@ public class MouseClickListener implements ScreenMouseEvents.AllowMouseClick {
|
|||||||
return screen.hashCode();
|
return screen.hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
// handlers
|
|
||||||
|
|
||||||
private void handleBookEditScreenClick(BookEditScreen bookEditScreen) {
|
|
||||||
var accessor = (BookEditScreenAccessor) screen;
|
|
||||||
|
|
||||||
VirtualKeyboardScreen virtualKeyboardScreen;
|
|
||||||
if(accessor.midnightcontrols$isSigning()) {
|
|
||||||
virtualKeyboardScreen = new VirtualKeyboardScreen(accessor.midnightcontrols$getTitle(), (text) -> {
|
|
||||||
client.setScreen(bookEditScreen);
|
|
||||||
accessor.midnightcontrols$setTitle(text);
|
|
||||||
}, true);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
virtualKeyboardScreen = new VirtualKeyboardScreen(accessor.midnightcontrols$getCurrentPageContent(), (text) -> {
|
|
||||||
client.setScreen(bookEditScreen);
|
|
||||||
accessor.midnightcontrols$setPageContent(text);
|
|
||||||
accessor.midnightcontrols$getCurrentPageSelectionManager().putCursorAtEnd();
|
|
||||||
}, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
client.setScreen(virtualKeyboardScreen);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handleSignEditScreenClick(SignEditScreen signEditScreen) {
|
|
||||||
var accessor = (AbstractSignEditScreenAccessor) signEditScreen;
|
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handleTextFieldClick(TextFieldWidget textField) {
|
|
||||||
this.link = new ScreenLink(screen, calculatePathToElement(screen, textField));
|
|
||||||
var virtualKeyboardScreen = new VirtualKeyboardScreen(textField.getText(), this::handleKeyboardClose, false);
|
|
||||||
client.setScreen(virtualKeyboardScreen);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handleKeyboardClose(String newText) {
|
|
||||||
if(this.link == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
client.setScreen(this.link.screen());
|
|
||||||
var txtField = findTextFieldByPath(screen, this.link.elementPath());
|
|
||||||
if (txtField == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
txtField.setText(newText);
|
|
||||||
|
|
||||||
switch (this.link.screen()) {
|
|
||||||
case CreativeInventoryScreen creativeInventoryScreen -> {
|
|
||||||
var accessor = (CreativeInventoryScreenAccessor) creativeInventoryScreen;
|
|
||||||
accessor.midnightcontrols$search();
|
|
||||||
}
|
|
||||||
case ChatScreen chatScreen -> {
|
|
||||||
// send the chat message
|
|
||||||
chatScreen.keyPressed(GLFW.GLFW_KEY_ENTER, 0, 0);
|
|
||||||
}
|
|
||||||
default -> {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// utility
|
|
||||||
|
|
||||||
private TextFieldWidget findClickedTextField(Screen screen, double mouseX, double mouseY) {
|
|
||||||
for (Element element : screen.children()) {
|
|
||||||
if (element instanceof TextFieldWidget textField) {
|
|
||||||
if (textField.isMouseOver(mouseX, mouseY) && textField.isFocused()) {
|
|
||||||
return textField;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// not hovering over a text field
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculates the path between a parent and a target in the UI hierarchy
|
|
||||||
*/
|
|
||||||
private List<Integer> calculatePathToElement(Element parent, Element target) {
|
|
||||||
if (parent instanceof ParentElement parentElement) {
|
|
||||||
List<? extends Element> children = parentElement.children();
|
|
||||||
|
|
||||||
// check direct children first
|
|
||||||
for (int i = 0; i < children.size(); i++) {
|
|
||||||
if (children.get(i) == target) {
|
|
||||||
// found it, return the path to this element
|
|
||||||
return Collections.singletonList(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// check each child's children
|
|
||||||
for (int i = 0; i < children.size(); i++) {
|
|
||||||
if (children.get(i) instanceof ParentElement childParent) {
|
|
||||||
List<Integer> subPath = calculatePathToElement(childParent, target);
|
|
||||||
if (subPath != null) {
|
|
||||||
// found in this subtree, prepend current index
|
|
||||||
List<Integer> fullPath = new ArrayList<>();
|
|
||||||
fullPath.add(i);
|
|
||||||
fullPath.addAll(subPath);
|
|
||||||
return fullPath;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Not found
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private TextFieldWidget findTextFieldByPath(Element parent, List<Integer> path) {
|
|
||||||
if (path == null || path.isEmpty()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parent instanceof ParentElement parentElement) {
|
|
||||||
List<? extends Element> children = parentElement.children();
|
|
||||||
int index = path.getFirst();
|
|
||||||
|
|
||||||
if (index >= 0 && index < children.size()) {
|
|
||||||
Element child = children.get(index);
|
|
||||||
|
|
||||||
if (path.size() == 1) {
|
|
||||||
// This should be our target
|
|
||||||
return (child instanceof TextFieldWidget) ? (TextFieldWidget) child : null;
|
|
||||||
} else {
|
|
||||||
// Continue traversing
|
|
||||||
if (child instanceof ParentElement) {
|
|
||||||
return findTextFieldByPath(child, path.subList(1, path.size()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig;
|
|||||||
import eu.midnightdust.midnightcontrols.client.util.platform.NetworkUtil;
|
import eu.midnightdust.midnightcontrols.client.util.platform.NetworkUtil;
|
||||||
import eu.midnightdust.midnightcontrols.packet.ControlsModePayload;
|
import eu.midnightdust.midnightcontrols.packet.ControlsModePayload;
|
||||||
import eu.midnightdust.midnightcontrols.packet.HelloPayload;
|
import eu.midnightdust.midnightcontrols.packet.HelloPayload;
|
||||||
|
import net.minecraft.client.gui.screen.Screen;
|
||||||
import net.minecraft.resource.DirectoryResourcePack;
|
import net.minecraft.resource.DirectoryResourcePack;
|
||||||
import net.minecraft.resource.ResourcePackInfo;
|
import net.minecraft.resource.ResourcePackInfo;
|
||||||
import net.minecraft.resource.ResourcePackPosition;
|
import net.minecraft.resource.ResourcePackPosition;
|
||||||
@@ -21,6 +22,7 @@ import net.neoforged.fml.common.Mod;
|
|||||||
import net.neoforged.neoforge.client.event.ClientPlayerNetworkEvent;
|
import net.neoforged.neoforge.client.event.ClientPlayerNetworkEvent;
|
||||||
import net.neoforged.neoforge.client.event.ClientTickEvent;
|
import net.neoforged.neoforge.client.event.ClientTickEvent;
|
||||||
import net.neoforged.neoforge.client.event.RegisterKeyMappingsEvent;
|
import net.neoforged.neoforge.client.event.RegisterKeyMappingsEvent;
|
||||||
|
import net.neoforged.neoforge.client.event.ScreenEvent;
|
||||||
import net.neoforged.neoforge.event.AddPackFindersEvent;
|
import net.neoforged.neoforge.event.AddPackFindersEvent;
|
||||||
import net.neoforged.neoforgespi.locating.IModFile;
|
import net.neoforged.neoforgespi.locating.IModFile;
|
||||||
|
|
||||||
@@ -34,6 +36,8 @@ import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.BIN
|
|||||||
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.BINDING_LOOK_UP;
|
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.BINDING_LOOK_UP;
|
||||||
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.BINDING_RING;
|
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.BINDING_RING;
|
||||||
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.client;
|
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.client;
|
||||||
|
import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.clickInterceptor;
|
||||||
|
|
||||||
|
|
||||||
@Mod(value = NAMESPACE, dist = Dist.CLIENT)
|
@Mod(value = NAMESPACE, dist = Dist.CLIENT)
|
||||||
public class MidnightControlsClientNeoforge {
|
public class MidnightControlsClientNeoforge {
|
||||||
@@ -90,5 +94,15 @@ public class MidnightControlsClientNeoforge {
|
|||||||
public static void startClientTick(ClientTickEvent.Pre event) {
|
public static void startClientTick(ClientTickEvent.Pre event) {
|
||||||
MidnightControlsClient.onTick(client);
|
MidnightControlsClient.onTick(client);
|
||||||
}
|
}
|
||||||
|
@SubscribeEvent
|
||||||
|
public static void onMouseButtonPressed(ScreenEvent.MouseButtonPressed.Pre event) {
|
||||||
|
if (!event.isCanceled()) {
|
||||||
|
Screen screen = event.getScreen();
|
||||||
|
double mouseX = event.getMouseX();
|
||||||
|
double mouseY = event.getMouseY();
|
||||||
|
|
||||||
|
clickInterceptor.intercept(screen, mouseX, mouseY);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user