diff --git a/src/client/java/works/nuty/calcite/mixin/client/ChatInputSuggestorFields.java b/src/client/java/works/nuty/calcite/mixin/client/ChatInputSuggestorFields.java new file mode 100644 index 0000000..5dfd8a7 --- /dev/null +++ b/src/client/java/works/nuty/calcite/mixin/client/ChatInputSuggestorFields.java @@ -0,0 +1,28 @@ +package works.nuty.calcite.mixin.client; + +import com.mojang.brigadier.ParseResults; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.client.gui.screen.ChatInputSuggestor; +import net.minecraft.command.CommandSource; +import net.minecraft.text.OrderedText; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import java.util.List; + +@Environment(EnvType.CLIENT) +@Mixin(ChatInputSuggestor.class) +public interface ChatInputSuggestorFields { + @Accessor + ChatInputSuggestor.SuggestionWindow getWindow(); + + @Accessor + int getMaxSuggestionSize(); + + @Accessor + ParseResults getParse(); + + @Accessor + List getMessages(); +} diff --git a/src/client/java/works/nuty/calcite/mixin/client/SuggestionWindowFields.java b/src/client/java/works/nuty/calcite/mixin/client/SuggestionWindowFields.java new file mode 100644 index 0000000..6a5097d --- /dev/null +++ b/src/client/java/works/nuty/calcite/mixin/client/SuggestionWindowFields.java @@ -0,0 +1,21 @@ +package works.nuty.calcite.mixin.client; + +import com.mojang.brigadier.suggestion.Suggestion; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.client.gui.screen.ChatInputSuggestor; +import net.minecraft.client.util.math.Rect2i; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import java.util.List; + +@Environment(EnvType.CLIENT) +@Mixin(ChatInputSuggestor.SuggestionWindow.class) +public interface SuggestionWindowFields { + @Accessor + Rect2i getArea(); + + @Accessor + List getSuggestions(); +} diff --git a/src/client/java/works/nuty/calcite/mixin/client/SuggestionWindowMixin.java b/src/client/java/works/nuty/calcite/mixin/client/SuggestionWindowMixin.java new file mode 100644 index 0000000..3441b12 --- /dev/null +++ b/src/client/java/works/nuty/calcite/mixin/client/SuggestionWindowMixin.java @@ -0,0 +1,45 @@ +package works.nuty.calcite.mixin.client; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.client.gui.screen.ChatInputSuggestor; +import org.lwjgl.glfw.GLFW; +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.CallbackInfoReturnable; + +@Environment(EnvType.CLIENT) +@Mixin(ChatInputSuggestor.SuggestionWindow.class) +public abstract class SuggestionWindowMixin { + @Shadow + boolean completed; + + @Shadow + public abstract void scroll(int offset); + + @Shadow + public abstract void complete(); + + @Inject(at = @At("HEAD"), method = "keyPressed", cancellable = true) + public void keyPressed(int keyCode, int scanCode, int modifiers, CallbackInfoReturnable cir) { + if ((modifiers & GLFW.GLFW_MOD_CONTROL) > 0 && keyCode == GLFW.GLFW_KEY_N) { + this.scroll(1); + this.completed = false; + cir.setReturnValue(true); + cir.cancel(); + } + if ((modifiers & GLFW.GLFW_MOD_CONTROL) > 0 && keyCode == GLFW.GLFW_KEY_P) { + this.scroll(-1); + this.completed = false; + cir.setReturnValue(true); + cir.cancel(); + } + if (keyCode == GLFW.GLFW_KEY_ENTER || keyCode == GLFW.GLFW_KEY_KP_ENTER) { + this.complete(); + cir.setReturnValue(true); + cir.cancel(); + } + } +} diff --git a/src/client/java/works/nuty/calcite/screen/CalciteCommandScreen.java b/src/client/java/works/nuty/calcite/screen/CalciteCommandScreen.java index 93f3ea1..93ab0ec 100644 --- a/src/client/java/works/nuty/calcite/screen/CalciteCommandScreen.java +++ b/src/client/java/works/nuty/calcite/screen/CalciteCommandScreen.java @@ -11,6 +11,7 @@ import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.Element; import net.minecraft.client.gui.Selectable; +import net.minecraft.client.gui.screen.ChatInputSuggestor; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.widget.ButtonWidget; import net.minecraft.client.gui.widget.ClickableWidget; @@ -25,6 +26,8 @@ import net.minecraft.world.World; import org.jetbrains.annotations.Nullable; import org.lwjgl.glfw.GLFW; +import works.nuty.calcite.mixin.client.ChatInputSuggestorFields; +import works.nuty.calcite.mixin.client.SuggestionWindowFields; import works.nuty.calcite.widget.AutoActivateButtonWidget; import works.nuty.calcite.widget.CalciteTextFieldWidget; import works.nuty.calcite.widget.ModeButtonWidget; @@ -347,7 +350,7 @@ public void scrollToFocused() { @Environment(EnvType.CLIENT) public class CommandWidget extends AbstractCommandWidget { - protected final CalciteInputSuggestor commandSuggestor; + protected final ChatInputSuggestor commandSuggestor; protected final List children; private final CommandBlockBlockEntity blockEntity; private final CalciteTextFieldWidget commandEdit; @@ -368,10 +371,11 @@ public CommandWidget(CommandBlockBlockEntity blockEntity) { this.commandEdit.setMaxLength(32500); this.commandEdit.setChangedListener(this::onCommandChanged); - this.commandSuggestor = new CalciteInputSuggestor(CalciteCommandScreen.this.client, CalciteCommandScreen.this, this.commandEdit, CalciteCommandScreen.this.textRenderer, true, true, 0, 7, Integer.MIN_VALUE); + this.commandSuggestor = new ChatInputSuggestor(CalciteCommandScreen.this.client, CalciteCommandScreen.this, this.commandEdit, CalciteCommandScreen.this.textRenderer, true, true, 0, 7, false, Integer.MIN_VALUE); this.commandSuggestor.setWindowActive(true); this.commandSuggestor.refresh(); + this.commandEdit.suggestor = this.commandSuggestor; this.commandEdit.setSuggestion(null); this.children = List.of(this.commandEdit); @@ -503,11 +507,14 @@ public void render(DrawContext context, int index, int y, int x, int entryWidth, CalciteCommandScreen.this.commandSuggestorRenderer = () -> { context.getMatrices().push(); context.getMatrices().translate(0, 0, 1); - CalciteInputSuggestor.SuggestionWindow window = this.commandSuggestor.window; + ChatInputSuggestor.SuggestionWindow window = ((ChatInputSuggestorFields) this.commandSuggestor).getWindow(); if (window != null) { - window.area.setY(window.calculateY(y)); + ((SuggestionWindowFields) window).getArea().setY(calculateSuggestionY(y)); + } + if (!this.commandSuggestor.tryRenderWindow(context, mouseX, mouseY)) { + context.getMatrices().translate(0, calculateMessageY(y), 0); + this.commandSuggestor.renderMessages(context); } - this.commandSuggestor.render(context, mouseX, mouseY, y); context.getMatrices().pop(); }; } @@ -531,5 +538,17 @@ protected void syncSettingsToServer() { CommandBlockExecutor commandExecutor = blockEntity.getCommandExecutor(); CalciteCommandScreen.this.client.getNetworkHandler().sendPacket(new UpdateCommandBlockC2SPacket(BlockPos.ofFloored(commandExecutor.getPos()), this.commandEdit.getText(), this.mode, commandExecutor.isTrackingOutput(), this.conditional, this.autoActivate)); } + + private int calculateSuggestionY(int y) { + return height / 2 - 6 < y + ? y - 3 - Math.min(((SuggestionWindowFields) ((ChatInputSuggestorFields) this.commandSuggestor).getWindow()).getSuggestions().size(), ((ChatInputSuggestorFields) this.commandSuggestor).getMaxSuggestionSize()) * 12 + : (y + 24) - (this.commandEdit.drawsBackground() ? 1 : 0); + } + + private int calculateMessageY(int y) { + return (height / 2 - 6 < y + ? y - 3 - ((ChatInputSuggestorFields) this.commandSuggestor).getMessages().size() * 12 + : (y + 24) - (this.commandEdit.drawsBackground() ? 1 : 0)) - 72; + } } } \ No newline at end of file diff --git a/src/client/java/works/nuty/calcite/screen/CalciteInputSuggestor.java b/src/client/java/works/nuty/calcite/screen/CalciteInputSuggestor.java deleted file mode 100644 index 93488d2..0000000 --- a/src/client/java/works/nuty/calcite/screen/CalciteInputSuggestor.java +++ /dev/null @@ -1,527 +0,0 @@ -package works.nuty.calcite.screen; - -import com.google.common.base.Strings; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Lists; -import com.mojang.brigadier.CommandDispatcher; -import com.mojang.brigadier.Message; -import com.mojang.brigadier.ParseResults; -import com.mojang.brigadier.StringReader; -import com.mojang.brigadier.context.CommandContextBuilder; -import com.mojang.brigadier.context.ParsedArgument; -import com.mojang.brigadier.context.SuggestionContext; -import com.mojang.brigadier.exceptions.CommandSyntaxException; -import com.mojang.brigadier.suggestion.Suggestion; -import com.mojang.brigadier.suggestion.Suggestions; -import com.mojang.brigadier.suggestion.SuggestionsBuilder; -import com.mojang.brigadier.tree.CommandNode; -import com.mojang.brigadier.tree.LiteralCommandNode; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.font.TextRenderer; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.client.util.math.Rect2i; -import net.minecraft.command.CommandSource; -import net.minecraft.screen.ScreenTexts; -import net.minecraft.server.command.CommandManager; -import net.minecraft.text.OrderedText; -import net.minecraft.text.Style; -import net.minecraft.text.Text; -import net.minecraft.text.Texts; -import net.minecraft.util.Colors; -import net.minecraft.util.Formatting; -import net.minecraft.util.math.MathHelper; -import net.minecraft.util.math.Vec2f; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.jetbrains.annotations.Nullable; -import works.nuty.calcite.widget.CalciteTextFieldWidget; - -import java.util.*; -import java.util.concurrent.CompletableFuture; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Stream; - -@Environment(EnvType.CLIENT) -public class CalciteInputSuggestor { - private static final Pattern WHITESPACE_PATTERN = Pattern.compile("(\\s+)"); - private static final Style ERROR_STYLE = Style.EMPTY.withColor(Formatting.RED); - private static final Style INFO_STYLE = Style.EMPTY.withColor(Formatting.GRAY); - private static final List