diff options
Diffstat (limited to 'src/main/java/at/hannibal2/skyhanni/mixins')
3 files changed, 83 insertions, 41 deletions
diff --git a/src/main/java/at/hannibal2/skyhanni/mixins/init/BeforeForLoopInjectionPoint.java b/src/main/java/at/hannibal2/skyhanni/mixins/init/BeforeForLoopInjectionPoint.java new file mode 100644 index 000000000..5316a8258 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/mixins/init/BeforeForLoopInjectionPoint.java @@ -0,0 +1,59 @@ +package at.hannibal2.skyhanni.mixins.init; + +import org.spongepowered.asm.lib.Opcodes; +import org.spongepowered.asm.lib.tree.AbstractInsnNode; +import org.spongepowered.asm.lib.tree.InsnList; +import org.spongepowered.asm.lib.tree.VarInsnNode; +import org.spongepowered.asm.mixin.injection.InjectionPoint; +import org.spongepowered.asm.mixin.injection.struct.InjectionPointData; + +import java.util.Collection; + +/** + * Inject just before a for loop which iterates over a local variable containing an array. + * + * <pre>{@code + * String [] s = new String[10]; + * + * // <-- Injection point here + * for (String e : s) { + * + * } + * } + * </pre> + * Does not work for more complex instructions which call functions or do other operations inside of the for loop header. + * Does not work for {@link java.util.Iterator iterators}. + * + * <p>Set the lvIndex arg to specify which lvIndex to search for when selecting the loop.</p> + * + * + * <pre>{@code + * @Inject(method = "...", at = @At(value = "SKYHANNI_FORLOOP_LOCAL_VAR", args = "lvIndex=1")) + * }</pre> + */ +@InjectionPoint.AtCode("SKYHANNI_FORLOOP_LOCAL_VAR") +public class BeforeForLoopInjectionPoint extends InjectionPoint { + private final int lvIndex; + + public BeforeForLoopInjectionPoint(InjectionPointData data) { + lvIndex = data.get("lvIndex", -1); + } + + @Override + public boolean find(String s, InsnList insnList, Collection<AbstractInsnNode> collection) { + for (AbstractInsnNode p = insnList.getFirst(); p != null; p = p.getNext()) { + if (p.getOpcode() != Opcodes.ARRAYLENGTH) { + continue; + } + AbstractInsnNode loadLoopVar = p.getPrevious(); + if (loadLoopVar == null || loadLoopVar.getOpcode() != Opcodes.ALOAD) continue; + AbstractInsnNode storeLoopVar = loadLoopVar.getPrevious(); + if (storeLoopVar == null || storeLoopVar.getOpcode() != Opcodes.ASTORE) continue; + AbstractInsnNode loadLoopArg = storeLoopVar.getPrevious(); + if (loadLoopArg == null || loadLoopArg.getOpcode() != Opcodes.ALOAD) continue; + if (lvIndex != -1 && ((VarInsnNode) loadLoopArg).var != lvIndex) continue; + collection.add(loadLoopArg); + } + return false; + } +} diff --git a/src/main/java/at/hannibal2/skyhanni/mixins/init/SkyhanniMixinPlugin.java b/src/main/java/at/hannibal2/skyhanni/mixins/init/SkyhanniMixinPlugin.java index 1f1b0e1fe..9dd4cc6f8 100644 --- a/src/main/java/at/hannibal2/skyhanni/mixins/init/SkyhanniMixinPlugin.java +++ b/src/main/java/at/hannibal2/skyhanni/mixins/init/SkyhanniMixinPlugin.java @@ -3,6 +3,7 @@ package at.hannibal2.skyhanni.mixins.init; import org.spongepowered.asm.lib.tree.ClassNode; import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin; import org.spongepowered.asm.mixin.extensibility.IMixinInfo; +import org.spongepowered.asm.mixin.injection.InjectionPoint; import java.io.IOException; import java.net.MalformedURLException; @@ -21,7 +22,7 @@ import java.util.zip.ZipInputStream; public class SkyhanniMixinPlugin implements IMixinConfigPlugin { @Override public void onLoad(String mixinPackage) { - + InjectionPoint.register(BeforeForLoopInjectionPoint.class); } @Override diff --git a/src/main/java/at/hannibal2/skyhanni/mixins/transformers/MixinGuiChat.java b/src/main/java/at/hannibal2/skyhanni/mixins/transformers/MixinGuiChat.java index 97ef80364..ff744b7d0 100644 --- a/src/main/java/at/hannibal2/skyhanni/mixins/transformers/MixinGuiChat.java +++ b/src/main/java/at/hannibal2/skyhanni/mixins/transformers/MixinGuiChat.java @@ -1,24 +1,22 @@ package at.hannibal2.skyhanni.mixins.transformers; import at.hannibal2.skyhanni.events.ChatHoverEvent; -import at.hannibal2.skyhanni.features.commands.tabcomplete.TabComplete; +import at.hannibal2.skyhanni.events.TabCompletionEvent; import at.hannibal2.skyhanni.mixins.hooks.GuiChatHook; -import com.google.common.collect.Lists; import net.minecraft.client.gui.GuiChat; import net.minecraft.client.gui.GuiTextField; import net.minecraft.util.ChatComponentText; -import net.minecraft.util.EnumChatFormatting; import net.minecraft.util.IChatComponent; -import org.apache.commons.lang3.StringUtils; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.ModifyArg; +import org.spongepowered.asm.mixin.injection.ModifyVariable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.LocalCapture; -import java.util.List; +import java.util.Arrays; @Mixin(GuiChat.class) public class MixinGuiChat { @@ -26,41 +24,25 @@ public class MixinGuiChat { @Shadow protected GuiTextField inputField; - @Shadow - private boolean waitingOnAutocomplete; - - @Shadow - private boolean playerNamesFound; - - @Shadow - private List<String> foundPlayerNames = Lists.newArrayList(); - - @Inject(method = "onAutocompleteResponse", at = @At(value = "HEAD"), cancellable = true) - private void renderItemOverlayPost(String[] originalArray, CallbackInfo ci) { - - if (this.waitingOnAutocomplete) { - String[] result = TabComplete.handleTabComplete(this.inputField.getText(), originalArray); - if (result == null) return; - ci.cancel(); - - this.playerNamesFound = false; - this.foundPlayerNames.clear(); - for (String s : result) { - if (!s.isEmpty()) { - this.foundPlayerNames.add(s); - } - } - - String s1 = this.inputField.getText().substring(this.inputField.func_146197_a(-1, this.inputField.getCursorPosition(), false)); - String s2 = StringUtils.getCommonPrefix(result); - s2 = EnumChatFormatting.getTextWithoutFormattingCodes(s2); - if (!s2.isEmpty() && !s1.equalsIgnoreCase(s2)) { - this.inputField.deleteFromCursor(this.inputField.func_146197_a(-1, this.inputField.getCursorPosition(), false) - this.inputField.getCursorPosition()); - this.inputField.writeText(s2); - } else if (!this.foundPlayerNames.isEmpty()) { - this.playerNamesFound = true; - } - } + @ModifyVariable( + method = "onAutocompleteResponse", + at = @At( + value = "SKYHANNI_FORLOOP_LOCAL_VAR", + shift = At.Shift.BEFORE, + args = "lvIndex=1" + ), + index = 1, + argsOnly = true + ) + private String[] renderItemOverlayPost(String[] originalArray) { + String inputFieldText = this.inputField.getText(); + String beforeCursor = inputFieldText.substring(0, this.inputField.getCursorPosition()); + TabCompletionEvent tabCompletionEvent = new TabCompletionEvent(beforeCursor, inputFieldText, Arrays.asList(originalArray)); + tabCompletionEvent.postAndCatch(); + String[] newSuggestions = tabCompletionEvent.intoSuggestionArray(); + if (newSuggestions == null) + newSuggestions = originalArray; + return newSuggestions; } @Inject(method = "drawScreen", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/GuiChat;handleComponentHover(Lnet/minecraft/util/IChatComponent;II)V"), locals = LocalCapture.CAPTURE_FAILHARD) |
