forked from Clones/Controlify
🐛 Fix issue with some modded GUIs crashing with controlify (closes #174)
This commit is contained in:
@ -3,12 +3,16 @@ package dev.isxander.controlify.mixins.core;
|
||||
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
|
||||
import dev.isxander.controlify.Controlify;
|
||||
import dev.isxander.controlify.ControllerManager;
|
||||
import dev.isxander.controlify.api.ControlifyApi;
|
||||
import dev.isxander.controlify.controller.Controller;
|
||||
import dev.isxander.controlify.utils.Animator;
|
||||
import dev.isxander.controlify.utils.MouseMinecraftCallNotifier;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.MouseHandler;
|
||||
import net.minecraft.client.gui.screens.Screen;
|
||||
import net.minecraft.server.packs.resources.ReloadInstance;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
@ -21,8 +25,30 @@ public abstract class MinecraftMixin {
|
||||
@Shadow public abstract void setScreen(@Nullable Screen screen);
|
||||
@Shadow public abstract float getDeltaFrameTime();
|
||||
|
||||
@Shadow @Final public MouseHandler mouseHandler;
|
||||
@Unique private boolean initNextTick = false;
|
||||
|
||||
// Ideally, this would be done in MouseHandler#releaseMouse, but moving
|
||||
// the mouse before the screen init is bad, because some mods (e.g. PuzzleLib)
|
||||
// have custom mouse events that call into screens, events that have not been
|
||||
// initialised yet in Screen#init. Causing NPEs and many strange issues.
|
||||
@Inject(method = "setScreen", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/MouseHandler;releaseMouse()V", shift = At.Shift.BEFORE))
|
||||
private void notifyInjectionToNotRun(Screen screen, CallbackInfo ci) {
|
||||
((MouseMinecraftCallNotifier) mouseHandler).imFromMinecraftSetScreen();
|
||||
}
|
||||
|
||||
/**
|
||||
* Without this, the mouse would be left in the middle of the
|
||||
* screen, hovering over whatever is there which would look wrong
|
||||
* as there is a focus as well.
|
||||
*/
|
||||
@Inject(method = "setScreen", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/Screen;init(Lnet/minecraft/client/Minecraft;II)V", shift = At.Shift.AFTER))
|
||||
private void hideMouseAfterRelease(Screen screen, CallbackInfo ci) {
|
||||
if (ControlifyApi.get().currentInputMode().isController()) {
|
||||
Controlify.instance().hideMouse(true, true);
|
||||
}
|
||||
}
|
||||
|
||||
@ModifyExpressionValue(method = "<init>", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/packs/resources/ReloadableResourceManager;createReload(Ljava/util/concurrent/Executor;Ljava/util/concurrent/Executor;Ljava/util/concurrent/CompletableFuture;Ljava/util/List;)Lnet/minecraft/server/packs/resources/ReloadInstance;"))
|
||||
private ReloadInstance onInputInitialized(ReloadInstance resourceReload) {
|
||||
// Controllers need to be initialized extremely late due to the data-driven nature of controllers.
|
||||
|
@ -3,19 +3,23 @@ package dev.isxander.controlify.mixins.core;
|
||||
import dev.isxander.controlify.Controlify;
|
||||
import dev.isxander.controlify.InputMode;
|
||||
import dev.isxander.controlify.api.ControlifyApi;
|
||||
import dev.isxander.controlify.utils.MouseMinecraftCallNotifier;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.MouseHandler;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
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.callback.CallbackInfo;
|
||||
|
||||
@Mixin(MouseHandler.class)
|
||||
public class MouseHandlerMixin {
|
||||
public class MouseHandlerMixin implements MouseMinecraftCallNotifier {
|
||||
@Shadow @Final private Minecraft minecraft;
|
||||
|
||||
@Unique private boolean calledFromMinecraftSetScreen = false;
|
||||
|
||||
// method_22686 is lambda for GLFW mouse click hook - do it outside of the `onPress` method due to fake inputs
|
||||
@Inject(method = "method_22686", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/MouseHandler;onPress(JIII)V"))
|
||||
private void onMouseClickInput(long window, int button, int action, int modifiers, CallbackInfo ci) {
|
||||
@ -34,6 +38,7 @@ public class MouseHandlerMixin {
|
||||
onMouse(window);
|
||||
}
|
||||
|
||||
@Unique
|
||||
private void onMouse(long window) {
|
||||
if (window == minecraft.getWindow().getWindow()) {
|
||||
if (Controlify.instance().currentInputMode() != InputMode.MIXED) {
|
||||
@ -49,8 +54,19 @@ public class MouseHandlerMixin {
|
||||
*/
|
||||
@Inject(method = "releaseMouse", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/platform/InputConstants;grabOrReleaseMouse(JIDD)V"))
|
||||
private void moveMouseIfNecessary(CallbackInfo ci) {
|
||||
if (ControlifyApi.get().currentInputMode().isController()) {
|
||||
if (!calledFromMinecraftSetScreen && ControlifyApi.get().currentInputMode().isController()) {
|
||||
Controlify.instance().hideMouse(true, true);
|
||||
}
|
||||
}
|
||||
|
||||
// shift after RETURN to escape the if statement scope
|
||||
@Inject(method = "releaseMouse", at = @At(value = "RETURN"))
|
||||
private void resetCalledFromMinecraftSetScreen(CallbackInfo ci) {
|
||||
calledFromMinecraftSetScreen = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void imFromMinecraftSetScreen() {
|
||||
calledFromMinecraftSetScreen = true;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,5 @@
|
||||
package dev.isxander.controlify.utils;
|
||||
|
||||
public interface MouseMinecraftCallNotifier {
|
||||
void imFromMinecraftSetScreen();
|
||||
}
|
Reference in New Issue
Block a user