From f263908f5fd482f2c17b07bf9c2994ea20539928 Mon Sep 17 00:00:00 2001 From: Martin Prokoph Date: Thu, 8 May 2025 00:08:27 +0200 Subject: [PATCH] fix: multiple touch-related bug fixes --- .../client/mixin/AbstractBlockAccessor.java | 14 ++++++++++ .../client/mixin/MinecraftClientMixin.java | 28 +++++++++++++++---- .../client/mixin/MouseMixin.java | 1 + .../client/touch/TouchUtils.java | 2 +- .../touch/gui/SilentTexturedButtonWidget.java | 2 ++ .../client/touch/gui/TouchscreenOverlay.java | 16 ++++++----- .../resources/midnightcontrols.mixins.json | 3 +- 7 files changed, 51 insertions(+), 15 deletions(-) create mode 100644 common/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/AbstractBlockAccessor.java diff --git a/common/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/AbstractBlockAccessor.java b/common/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/AbstractBlockAccessor.java new file mode 100644 index 0000000..5f6b874 --- /dev/null +++ b/common/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/AbstractBlockAccessor.java @@ -0,0 +1,14 @@ +package eu.midnightdust.midnightcontrols.client.mixin; + +import net.minecraft.block.AbstractBlock; +import net.minecraft.block.BlockState; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.WorldView; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +@Mixin(AbstractBlock.class) +public interface AbstractBlockAccessor { + @Invoker("canPlaceAt") + boolean midnightcontrols$canPlaceAt(BlockState state, WorldView world, BlockPos pos); +} diff --git a/common/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/MinecraftClientMixin.java b/common/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/MinecraftClientMixin.java index cdcad30..d277f58 100644 --- a/common/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/MinecraftClientMixin.java +++ b/common/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/MinecraftClientMixin.java @@ -28,6 +28,7 @@ import net.minecraft.util.hit.HitResult; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.util.math.Vec3d; +import net.minecraft.util.profiler.Profiler; import org.jetbrains.annotations.Nullable; import org.lwjgl.glfw.GLFW; import org.spongepowered.asm.mixin.Final; @@ -36,9 +37,9 @@ import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.client; import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.reacharound; @Mixin(MinecraftClient.class) @@ -55,6 +56,10 @@ public abstract class MinecraftClientMixin { @Shadow public abstract void setScreen(Screen screen); + @Shadow public int attackCooldown; + + @Shadow protected abstract void handleInputEvents(); + @Unique private BlockPos midnightcontrols$lastTargetPos; @Unique private Vec3d midnightcontrols$lastPos; @Unique private Direction midnightcontrols$lastTargetSide; @@ -145,10 +150,21 @@ public abstract class MinecraftClientMixin { } } } - // This is always supposed to be located at before the line 'this.profiler.swap("Keybindings");' - @Redirect(method = "tick", at = @At(value = "FIELD",target = "Lnet/minecraft/client/MinecraftClient;currentScreen:Lnet/minecraft/client/gui/screen/Screen;", ordinal = 6)) - private Screen midnightcontrols$keybindsIgnoreTouchOverlay(MinecraftClient instance) { - if (instance.currentScreen instanceof TouchscreenOverlay) return null; - return instance.currentScreen; + // TODO: Replace this with MixinExtras' Expressions once that's officially released + @Inject(method = "tick", at = @At(value = "INVOKE",target = "Lnet/minecraft/client/gui/hud/DebugHud;shouldShowDebugHud()Z")) + private void midnightcontrols$handleKeybindsWithTouchOverlay(CallbackInfo ci, @Local Profiler profiler) { + if (client.currentScreen instanceof TouchscreenOverlay) { + profiler.swap("Keybindings"); + this.handleInputEvents(); + if (this.attackCooldown > 0) { + --this.attackCooldown; + } + } + } + + // Needed, as it will cause item actions not to work in touchscreen mode otherwise with the above method + @Inject(method = "handleInputEvents", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;isUsingItem()Z"), cancellable = true) + private void midnightcontrols$dontHandleItemAndBlockInteractions(CallbackInfo ci) { + if (client.currentScreen instanceof TouchscreenOverlay) ci.cancel(); } } diff --git a/common/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/MouseMixin.java b/common/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/MouseMixin.java index cff8cfc..c251141 100644 --- a/common/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/MouseMixin.java +++ b/common/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/MouseMixin.java @@ -78,6 +78,7 @@ public abstract class MouseMixin implements MouseAccessor { int slotX = centerX - 90 + slot * 20 + 2; if (mouseX >= (double) slotX && mouseX <= (double) (slotX + 20)) { client.player.getInventory().setSelectedSlot(slot); + TouchInput.clickStartTime = -1; ci.cancel(); return; } diff --git a/common/src/main/java/eu/midnightdust/midnightcontrols/client/touch/TouchUtils.java b/common/src/main/java/eu/midnightdust/midnightcontrols/client/touch/TouchUtils.java index 403e7df..49b1e3f 100644 --- a/common/src/main/java/eu/midnightdust/midnightcontrols/client/touch/TouchUtils.java +++ b/common/src/main/java/eu/midnightdust/midnightcontrols/client/touch/TouchUtils.java @@ -38,7 +38,7 @@ public class TouchUtils { if (entityCast != null && entityCast.getType() == HitResult.Type.ENTITY) return entityCast; - BlockHitResult result = client.world.raycast(new RaycastContext(near, far, RaycastContext.ShapeType.OUTLINE, RaycastContext.FluidHandling.ANY, 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; return result; diff --git a/common/src/main/java/eu/midnightdust/midnightcontrols/client/touch/gui/SilentTexturedButtonWidget.java b/common/src/main/java/eu/midnightdust/midnightcontrols/client/touch/gui/SilentTexturedButtonWidget.java index c71ee85..b55c9f7 100644 --- a/common/src/main/java/eu/midnightdust/midnightcontrols/client/touch/gui/SilentTexturedButtonWidget.java +++ b/common/src/main/java/eu/midnightdust/midnightcontrols/client/touch/gui/SilentTexturedButtonWidget.java @@ -1,5 +1,6 @@ package eu.midnightdust.midnightcontrols.client.touch.gui; +import eu.midnightdust.midnightcontrols.client.touch.TouchInput; import org.thinkingstudio.obsidianui.Position; import org.thinkingstudio.obsidianui.widget.SpruceTexturedButtonWidget; import net.minecraft.text.Text; @@ -34,6 +35,7 @@ public class SilentTexturedButtonWidget extends SpruceTexturedButtonWidget { public void onClick(double mouseX, double mouseY) { this.setActive(true); super.onClick(mouseX, mouseY); + TouchInput.clickStartTime = -1; this.setActive(false); } } diff --git a/common/src/main/java/eu/midnightdust/midnightcontrols/client/touch/gui/TouchscreenOverlay.java b/common/src/main/java/eu/midnightdust/midnightcontrols/client/touch/gui/TouchscreenOverlay.java index 4101634..846225f 100644 --- a/common/src/main/java/eu/midnightdust/midnightcontrols/client/touch/gui/TouchscreenOverlay.java +++ b/common/src/main/java/eu/midnightdust/midnightcontrols/client/touch/gui/TouchscreenOverlay.java @@ -9,8 +9,10 @@ package eu.midnightdust.midnightcontrols.client.touch.gui; +import eu.midnightdust.midnightcontrols.client.mixin.KeyBindingIDAccessor; import eu.midnightdust.midnightcontrols.client.touch.TouchInput; import eu.midnightdust.midnightcontrols.client.util.storage.AxisStorage; +import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.screen.ChatScreen; import net.minecraft.client.gui.screen.GameMenuScreen; import net.minecraft.client.gui.screen.Screen; @@ -298,7 +300,13 @@ public class TouchscreenOverlay extends Screen { if (binding == null) continue; boolean hasTexture = client.getGuiAtlasManager().getSprite(id("binding/"+bindName)) != missingSprite; if (MidnightControlsConfig.debug) System.out.println(left +" "+id("binding/"+bindName)+" "+ hasTexture); - var button = TextIconButtonWidget.builder(Text.translatable(binding.getTranslationKey()), b -> binding.handle(client, 1, ButtonState.PRESS), hasTexture) + var button = TextIconButtonWidget.builder(Text.translatable(binding.getTranslationKey()), b -> { + binding.handle(client, 1.0f, ButtonState.PRESS); + if (binding.asKeyBinding().isPresent()) { + binding.asKeyBinding().get().setPressed(true); + ((KeyBindingAccessor)binding.asKeyBinding().get()).midnightcontrols$press(); + } + }, hasTexture) .texture(hasTexture ? id("binding/"+bindName) : emptySprite, 20, 20).dimension(20, 20).build(); button.setPosition(left ? (3+(i*23)) : this.width-(23+(i*23)), 3); button.setAlpha(MidnightControlsConfig.touchTransparency / 100f); @@ -359,10 +367,4 @@ public class TouchscreenOverlay extends Screen { } return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY); } - @Override - public boolean keyPressed(int keyCode, int scanCode, int modifiers) { - KeyBinding.onKeyPressed(InputUtil.fromKeyCode(keyCode, scanCode)); - super.keyPressed(keyCode,scanCode,modifiers); - return true; - } } diff --git a/common/src/main/resources/midnightcontrols.mixins.json b/common/src/main/resources/midnightcontrols.mixins.json index c42bcc5..6b902dd 100644 --- a/common/src/main/resources/midnightcontrols.mixins.json +++ b/common/src/main/resources/midnightcontrols.mixins.json @@ -24,7 +24,8 @@ "RecipeBookWidgetAccessor", "ScreenMixin", "TabNavigationWidgetAccessor", - "WorldRendererMixin" + "WorldRendererMixin", + "AbstractBlockAccessor" ], "injectors": { "defaultRequire": 1