From a3c36aac90580cff9d50113ce0a1a730991cc1b5 Mon Sep 17 00:00:00 2001 From: ZZZank <47418975+ZZZank@users.noreply.github.com> Date: Tue, 23 Jun 2026 14:00:46 +0800 Subject: [PATCH] replace reflection based action with mixin --- gradle.properties | 6 +- src/main/java/yalter/mousetweaks/Main.java | 6 +- .../handlers/GuiContainerHandler.java | 62 +++++-------------- .../handlers/IMTModGuiContainer2Handler.java | 31 +++------- .../impl/MouseTweaksMixinLoader.java | 41 ++++++++++++ .../impl/mixin/AccessGuiContainer.java | 30 +++++++++ .../mousetweaks/reflect/Reflection.java | 1 + .../mousetweaks/reflect/ReflectionCache.java | 1 + src/main/resources/mixins.mousetweaks.json | 12 ++++ 9 files changed, 116 insertions(+), 74 deletions(-) create mode 100644 src/main/java/yalter/mousetweaks/impl/MouseTweaksMixinLoader.java create mode 100644 src/main/java/yalter/mousetweaks/impl/mixin/AccessGuiContainer.java create mode 100644 src/main/resources/mixins.mousetweaks.json diff --git a/gradle.properties b/gradle.properties index e392876..c6f5842 100644 --- a/gradle.properties +++ b/gradle.properties @@ -49,12 +49,12 @@ apiPackage = accessTransformersFile = # Provides setup for Mixins if enabled. If you don't know what mixins are: Keep it disabled! -usesMixins = false +usesMixins = true # Specify the package that contains all of your Mixins. You may only place Mixins in this package or the build will fail! -mixinsPackage = +mixinsPackage = impl.mixin # Specify the core mod entry class if you use a core mod. This class must implement IFMLLoadingPlugin! # Example value: coreModClass = asm.FMLPlugin + modGroup = com.myname.mymodid -> com.myname.mymodid.asm.FMLPlugin -coreModClass = +coreModClass = impl.MouseTweaksMixinLoader # If your project is only a consolidation of mixins or a core mod and does NOT contain a 'normal' mod (meaning that # there is no class annotated with @Mod) you want this to be true. When in doubt: leave it on false! containsMixinsAndOrCoreModOnly = false diff --git a/src/main/java/yalter/mousetweaks/Main.java b/src/main/java/yalter/mousetweaks/Main.java index 84b31b7..fdf0f2e 100644 --- a/src/main/java/yalter/mousetweaks/Main.java +++ b/src/main/java/yalter/mousetweaks/Main.java @@ -13,7 +13,7 @@ import yalter.mousetweaks.api.IMTModGuiContainer2Ex; import yalter.mousetweaks.impl.*; import yalter.mousetweaks.handlers.*; -import yalter.mousetweaks.reflect.Reflection; +import yalter.mousetweaks.impl.mixin.AccessGuiContainer; import yalter.mousetweaks.util.MTLog; import java.util.List; @@ -38,7 +38,9 @@ public static boolean initialize() { return true; initialized = true; - Reflection.reflectGuiContainer(); + if (!AccessGuiContainer.class.isAssignableFrom(GuiContainer.class)) { + MTLog.logger.fatal("Unable to find injected mixin for GuiContainer class"); + } MTLog.logger.fatal("Mouse Tweaks has been initialized."); diff --git a/src/main/java/yalter/mousetweaks/handlers/GuiContainerHandler.java b/src/main/java/yalter/mousetweaks/handlers/GuiContainerHandler.java index c841a40..5137bd8 100644 --- a/src/main/java/yalter/mousetweaks/handlers/GuiContainerHandler.java +++ b/src/main/java/yalter/mousetweaks/handlers/GuiContainerHandler.java @@ -2,32 +2,25 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.gui.inventory.GuiContainer; -import net.minecraft.crash.CrashReport; import net.minecraft.inventory.*; import net.minecraft.item.ItemStack; -import net.minecraft.util.ReportedException; import org.lwjgl.input.Mouse; import yalter.mousetweaks.MouseTweaks; -import yalter.mousetweaks.util.Constants; +import yalter.mousetweaks.impl.mixin.AccessGuiContainer; import yalter.mousetweaks.impl.IGuiScreenHandler; import yalter.mousetweaks.impl.MouseButton; -import yalter.mousetweaks.reflect.Reflection; import yalter.mousetweaks.api.MouseTweaksDisableWheelTweak; import yalter.mousetweaks.api.MouseTweaksIgnore; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; import java.util.List; public class GuiContainerHandler implements IGuiScreenHandler { protected Minecraft mc; protected GuiContainer guiContainer; - protected Method handleMouseClick; public GuiContainerHandler(GuiContainer guiContainer) { this.mc = Minecraft.getMinecraft(); this.guiContainer = guiContainer; - this.handleMouseClick = Reflection.getHMCMethod(guiContainer); } private int getDisplayWidth() { @@ -48,8 +41,9 @@ private int getRequiredMouseY() { @Override public boolean isMouseTweaksDisabled() { - return guiContainer.getClass().isAnnotationPresent(MouseTweaksIgnore.class) || (Reflection.guiContainerClass - == null) || MouseTweaks.instance.isMouseTweakDisabled(guiContainer.getClass()); + return guiContainer.getClass().isAnnotationPresent(MouseTweaksIgnore.class) + || !(guiContainer instanceof AccessGuiContainer) + || MouseTweaks.instance.isMouseTweakDisabled(guiContainer.getClass()); } @Override @@ -65,30 +59,18 @@ public List getSlots() { @Override public Slot getSlotUnderMouse() { - try { - return (Slot) Reflection.guiContainerClass.invokeMethod(guiContainer, - Constants.GETSLOTATPOSITION_NAME.forgeName, - getRequiredMouseX(), - getRequiredMouseY()); - } catch (InvocationTargetException e) { - CrashReport crashreport = CrashReport.makeCrashReport(e, - "GuiContainer.getSlotAtPosition() threw an exception" - + " when called from MouseTweaks."); - throw new ReportedException(crashreport); - } + return ((AccessGuiContainer) guiContainer).invokeGetSlotAtPosition(getRequiredMouseX(), getRequiredMouseY()); } @Override public boolean disableRMBDraggingFunctionality() { - Reflection.guiContainerClass.setFieldValue(guiContainer, Constants.IGNOREMOUSEUP_NAME.forgeName, true); - - if ((Boolean) Reflection.guiContainerClass.getFieldValue(guiContainer, - Constants.DRAGSPLITTING_NAME.forgeName)) { - if ((Integer) Reflection.guiContainerClass.getFieldValue(guiContainer, - Constants.DRAGSPLITTINGBUTTON_NAME.forgeName) - == 1) { - Reflection.guiContainerClass.setFieldValue(guiContainer, Constants.DRAGSPLITTING_NAME.forgeName, - false); + var access = (AccessGuiContainer) guiContainer; + + access.setIgnoreMouseUp(true); + + if (access.getDragSplitting()) { + if (access.getDragSplittingButton() == 1) { + access.setIgnoreMouseUp(false); return true; } } @@ -98,21 +80,11 @@ public boolean disableRMBDraggingFunctionality() { @Override public void clickSlot(Slot slot, MouseButton mouseButton, boolean shiftPressed) { - try { - handleMouseClick.invoke(guiContainer, - slot, - slot.slotNumber, - mouseButton.getValue(), - shiftPressed ? ClickType.QUICK_MOVE : ClickType.PICKUP); - } catch (InvocationTargetException e) { - CrashReport crashreport = CrashReport.makeCrashReport(e, - "handleMouseClick() threw an exception when called " - + "from MouseTweaks."); - throw new ReportedException(crashreport); - } catch (IllegalAccessException e) { - CrashReport crashreport = CrashReport.makeCrashReport(e, "Calling handleMouseClick() from MouseTweaks."); - throw new ReportedException(crashreport); - } + ((AccessGuiContainer) this.guiContainer).invokeHandleMouseClick( + slot, + slot.slotNumber, + mouseButton.getValue(), + shiftPressed ? ClickType.QUICK_MOVE : ClickType.PICKUP); } @Override diff --git a/src/main/java/yalter/mousetweaks/handlers/IMTModGuiContainer2Handler.java b/src/main/java/yalter/mousetweaks/handlers/IMTModGuiContainer2Handler.java index 615d0bd..e107b04 100644 --- a/src/main/java/yalter/mousetweaks/handlers/IMTModGuiContainer2Handler.java +++ b/src/main/java/yalter/mousetweaks/handlers/IMTModGuiContainer2Handler.java @@ -1,29 +1,23 @@ package yalter.mousetweaks.handlers; import net.minecraft.client.Minecraft; -import net.minecraft.crash.CrashReport; import net.minecraft.inventory.ClickType; import net.minecraft.inventory.Slot; import net.minecraft.item.ItemStack; -import net.minecraft.util.ReportedException; import yalter.mousetweaks.impl.IGuiScreenHandler; import yalter.mousetweaks.impl.MouseButton; -import yalter.mousetweaks.reflect.Reflection; +import yalter.mousetweaks.impl.mixin.AccessGuiContainer; import yalter.mousetweaks.api.IMTModGuiContainer2; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; import java.util.List; public class IMTModGuiContainer2Handler implements IGuiScreenHandler { protected Minecraft mc; protected IMTModGuiContainer2 modGuiContainer; - protected Method handleMouseClick; public IMTModGuiContainer2Handler(IMTModGuiContainer2 modGuiContainer) { this.mc = Minecraft.getMinecraft(); this.modGuiContainer = modGuiContainer; - this.handleMouseClick = Reflection.getHMCMethod(modGuiContainer); } @Override @@ -53,23 +47,12 @@ public boolean disableRMBDraggingFunctionality() { @Override public void clickSlot(Slot slot, MouseButton mouseButton, boolean shiftPressed) { - if (handleMouseClick != null) { - try { - handleMouseClick.invoke(modGuiContainer, - slot, - slot.slotNumber, - mouseButton.getValue(), - shiftPressed ? ClickType.QUICK_MOVE : ClickType.PICKUP); - } catch (InvocationTargetException e) { - CrashReport crashreport = CrashReport.makeCrashReport(e, - "handleMouseClick() threw an exception when " - + "called from MouseTweaks."); - throw new ReportedException(crashreport); - } catch (IllegalAccessException e) { - CrashReport crashreport = CrashReport.makeCrashReport(e, - "Calling handleMouseClick() from MouseTweaks."); - throw new ReportedException(crashreport); - } + if (modGuiContainer instanceof AccessGuiContainer access) { + access.invokeHandleMouseClick( + slot, + slot.slotNumber, + mouseButton.getValue(), + shiftPressed ? ClickType.QUICK_MOVE : ClickType.PICKUP); } else { mc.playerController.windowClick(modGuiContainer.MT_getContainer().windowId, slot.slotNumber, diff --git a/src/main/java/yalter/mousetweaks/impl/MouseTweaksMixinLoader.java b/src/main/java/yalter/mousetweaks/impl/MouseTweaksMixinLoader.java new file mode 100644 index 0000000..1ec1835 --- /dev/null +++ b/src/main/java/yalter/mousetweaks/impl/MouseTweaksMixinLoader.java @@ -0,0 +1,41 @@ +package yalter.mousetweaks.impl; + +import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin; +import org.jetbrains.annotations.Nullable; +import zone.rong.mixinbooter.IEarlyMixinLoader; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +public class MouseTweaksMixinLoader implements IFMLLoadingPlugin, IEarlyMixinLoader { + + @Override + public List getMixinConfigs() { + return Collections.singletonList("mixins.mousetweaks.json"); + } + + @Override + public String[] getASMTransformerClass() { + return new String[0]; + } + + @Override + public String getModContainerClass() { + return null; + } + + @Override + public @Nullable String getSetupClass() { + return null; + } + + @Override + public void injectData(Map data) { + } + + @Override + public String getAccessTransformerClass() { + return null; + } +} diff --git a/src/main/java/yalter/mousetweaks/impl/mixin/AccessGuiContainer.java b/src/main/java/yalter/mousetweaks/impl/mixin/AccessGuiContainer.java new file mode 100644 index 0000000..d0a6f66 --- /dev/null +++ b/src/main/java/yalter/mousetweaks/impl/mixin/AccessGuiContainer.java @@ -0,0 +1,30 @@ +package yalter.mousetweaks.impl.mixin; + +import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.inventory.ClickType; +import net.minecraft.inventory.Slot; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; +import org.spongepowered.asm.mixin.gen.Invoker; + +/** + * @author ZZZank + */ +@Mixin(GuiContainer.class) +public interface AccessGuiContainer { + + @Invoker + void invokeHandleMouseClick(Slot slotIn, int slotId, int mouseButton, ClickType type); + + @Invoker + Slot invokeGetSlotAtPosition(int x, int y); + + @Accessor + void setIgnoreMouseUp(boolean value); + + @Accessor + boolean getDragSplitting(); + + @Accessor + int getDragSplittingButton(); +} diff --git a/src/main/java/yalter/mousetweaks/reflect/Reflection.java b/src/main/java/yalter/mousetweaks/reflect/Reflection.java index e3d7425..7118f09 100644 --- a/src/main/java/yalter/mousetweaks/reflect/Reflection.java +++ b/src/main/java/yalter/mousetweaks/reflect/Reflection.java @@ -14,6 +14,7 @@ import java.lang.reflect.Method; import java.util.HashMap; +@Deprecated public class Reflection { private static Obfuscation obfuscation; private static boolean checkObfuscation = true; diff --git a/src/main/java/yalter/mousetweaks/reflect/ReflectionCache.java b/src/main/java/yalter/mousetweaks/reflect/ReflectionCache.java index 4a14222..4e0a9d9 100644 --- a/src/main/java/yalter/mousetweaks/reflect/ReflectionCache.java +++ b/src/main/java/yalter/mousetweaks/reflect/ReflectionCache.java @@ -8,6 +8,7 @@ import java.lang.reflect.Method; import java.util.HashMap; +@Deprecated public class ReflectionCache { private final HashMap methods = new HashMap<>(); diff --git a/src/main/resources/mixins.mousetweaks.json b/src/main/resources/mixins.mousetweaks.json new file mode 100644 index 0000000..8df6657 --- /dev/null +++ b/src/main/resources/mixins.mousetweaks.json @@ -0,0 +1,12 @@ +{ + "package" : "yalter.mousetweaks.impl.mixin", + "refmap" : "mixins.mousetweaks.refmap.json", + "target" : "@env(DEFAULT)", + "minVersion" : "0.8", + "compatibilityLevel" : "JAVA_8", + "mixins" : [], + "client" : [ + "AccessGuiContainer" + ], + "server": [] +}