/* * Copyright (C) 2022 NotEnoughUpdates contributors * * This file is part of NotEnoughUpdates. * * NotEnoughUpdates is free software: you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation, either * version 3 of the License, or (at your option) any later version. * * NotEnoughUpdates is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with NotEnoughUpdates. If not, see . */ package io.github.moulberry.notenoughupdates.mixins; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; import net.minecraft.client.gui.GuiTextField; import org.lwjgl.input.Keyboard; 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.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import java.util.ArrayList; @Mixin(GuiTextField.class) public abstract class MixinGuiTextField { private final ArrayList stringStack = new ArrayList() { { //allows the ability to undo the entire textField add(""); } }; private int currentStringStackIndex = -1; @Shadow private int maxStringLength; @Shadow private String text; @Shadow public abstract void setCursorPositionEnd(); @Shadow public abstract void setText(String string); private void addToStack(String string) { if (currentStringStackIndex != -1 && currentStringStackIndex != stringStack.size() - 1) { //did redo/undo before stringStack.subList(currentStringStackIndex, stringStack.size()).clear(); } if (stringStack.size() > 20) { stringStack.remove(0); } stringStack.add(string); currentStringStackIndex = stringStack.size() - 1; } @Inject(method = "setText", at = @At("TAIL"), locals = LocalCapture.CAPTURE_FAILSOFT) public void setText_stringStack(String string, CallbackInfo ci) { if (NotEnoughUpdates.INSTANCE.config.misc.textFieldTweaksEnabled) { addToStack(string.length() > this.maxStringLength ? string.substring(0, this.maxStringLength) : string); } } @Inject(method = "writeText", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/GuiTextField;moveCursorBy(I)V"), locals = LocalCapture.CAPTURE_FAILSOFT) public void writeText_stringStack(String string, CallbackInfo ci, String string2, String string3, int i, int j, int l) { if (NotEnoughUpdates.INSTANCE.config.misc.textFieldTweaksEnabled) { addToStack(string2); } } @Inject(method = "deleteFromCursor", at = @At(value = "INVOKE", target = "Lcom/google/common/base/Predicate;apply(Ljava/lang/Object;)Z", remap = false), locals = LocalCapture.CAPTURE_FAILSOFT) public void deleteFromCursor_stringStack(int i, CallbackInfo ci, boolean bl, int j, int k, String string) { if (NotEnoughUpdates.INSTANCE.config.misc.textFieldTweaksEnabled) { addToStack(string); } } @Inject(method = "textboxKeyTyped", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/GuiScreen;isKeyComboCtrlA(I)Z"), cancellable = true) public void textboxKeyTyped_stringStack(char c, int i, CallbackInfoReturnable cir) { if (NotEnoughUpdates.INSTANCE.config.misc.textFieldTweaksEnabled) { if (Keyboard.isKeyDown(Keyboard.KEY_LCONTROL)) { if (currentStringStackIndex == -1 && stringStack.size() > 0) { currentStringStackIndex = stringStack.size() - 1; } if (Keyboard.isKeyDown(Keyboard.KEY_Y) || (Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) && Keyboard.isKeyDown( Keyboard.KEY_Z))) { //go forward in action stack if (currentStringStackIndex != stringStack.size() - 1) { text = stringStack.get(currentStringStackIndex + 1); currentStringStackIndex += 1; setCursorPositionEnd(); } cir.setReturnValue(true); } else if (Keyboard.isKeyDown(Keyboard.KEY_Z)) { //go back in action stack if (!stringStack.isEmpty() && currentStringStackIndex > 0 && stringStack.get(currentStringStackIndex - 1) != null) { text = stringStack.get(currentStringStackIndex - 1); currentStringStackIndex -= 1; setCursorPositionEnd(); } cir.setReturnValue(true); } } } } @Inject(method = "setMaxStringLength", at = @At(value = "INVOKE", target = "Ljava/lang/String;length()I")) public void setMaxStringLength_stringStack(int i, CallbackInfo ci) { //will remove the possibility of creating a bug in the matrix (untested) if (NotEnoughUpdates.INSTANCE.config.misc.textFieldTweaksEnabled) { for (int j = 0; j < stringStack.size(); j++) { String string = stringStack.get(j); if (string.length() > i) { stringStack.set(j, string.substring(0, j)); if (j < currentStringStackIndex) { currentStringStackIndex -= 1; } } } } } }