aboutsummaryrefslogtreecommitdiff
path: root/src/main/java
diff options
context:
space:
mode:
authornea <nea@nea.moe>2023-01-22 06:51:34 +0100
committernea <nea@nea.moe>2023-01-31 21:20:21 +0100
commit8fcdec089563455ae5080d17c66223082124b594 (patch)
tree7719737091fd97caeb815428a18a031ed0f5d47b /src/main/java
parent9fabe241cfe613b836335aa918b1a2423bfde31b (diff)
downloadNotEnoughUpdates-8fcdec089563455ae5080d17c66223082124b594.tar.gz
NotEnoughUpdates-8fcdec089563455ae5080d17c66223082124b594.tar.bz2
NotEnoughUpdates-8fcdec089563455ae5080d17c66223082124b594.zip
wip
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/AccessorCommandHandler.java33
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/brigadier/NEUBrigadierHook.kt92
2 files changed, 125 insertions, 0 deletions
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/AccessorCommandHandler.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/AccessorCommandHandler.java
new file mode 100644
index 00000000..73d31196
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/AccessorCommandHandler.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2023 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 <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.mixins;
+
+import net.minecraft.command.CommandHandler;
+import net.minecraft.command.ICommand;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.gen.Accessor;
+
+import java.util.Set;
+
+@Mixin(CommandHandler.class)
+public interface AccessorCommandHandler {
+ @Accessor("commandSet")
+ Set<ICommand> neuGetClientCommands();
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/brigadier/NEUBrigadierHook.kt b/src/main/java/io/github/moulberry/notenoughupdates/util/brigadier/NEUBrigadierHook.kt
new file mode 100644
index 00000000..b8ba7b48
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/brigadier/NEUBrigadierHook.kt
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2023 Linnea Gräf
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.util.brigadier
+
+import com.mojang.brigadier.ParseResults
+import com.mojang.brigadier.exceptions.CommandSyntaxException
+import com.mojang.brigadier.suggestion.Suggestions
+import com.mojang.brigadier.tree.CommandNode
+import net.minecraft.command.CommandBase
+import net.minecraft.command.ICommandSender
+import net.minecraft.util.BlockPos
+import net.minecraft.util.ChatComponentText
+import net.minecraft.util.EnumChatFormatting
+import java.util.concurrent.CompletableFuture
+import java.util.function.Predicate
+
+/**
+ * Hook for converting brigadier commands to normal legacy Minecraft commands (string array style).
+ */
+class NEUBrigadierHook(val brigadierRoot: BrigadierRoot, val commandNode: CommandNode<DefaultSource>) : CommandBase() {
+ /**
+ * Runs before the command gets executed. Return false to prevent execution.
+ */
+ var beforeCommand: Predicate<ParseResults<DefaultSource>>? = null
+
+ override fun getCommandName(): String {
+ return commandNode.name
+ }
+
+ override fun getCommandUsage(sender: ICommandSender): String {
+ return brigadierRoot.dispatcher.getAllUsage(commandNode, sender, true).joinToString("\n")
+ }
+
+ private fun getText(args: Array<out String>) = "${commandNode.name} ${args.joinToString(" ")}"
+
+ override fun processCommand(sender: ICommandSender, args: Array<out String>) {
+ val results = brigadierRoot.parseText.apply(sender to getText(args).trim())
+ if (beforeCommand?.test(results) == false)
+ return
+ try {
+ brigadierRoot.dispatcher.execute(results)
+ } catch (syntax: CommandSyntaxException) {
+ sender.addChatMessage(ChatComponentText("${EnumChatFormatting.RED}${syntax.message}"))
+ }
+ }
+
+ // We love async tab completion (may end up requiring pressing tab multiple times, but uhhhhh .get() bad)
+ private var lastCompletionText: String? = null
+ private var lastCompletion: CompletableFuture<Suggestions>? = null
+ override fun addTabCompletionOptions(
+ sender: ICommandSender,
+ args: Array<out String>,
+ pos: BlockPos
+ ): List<String> {
+ val originalText = getText(args)
+ var lc: CompletableFuture<Suggestions>? = null
+ if (lastCompletionText == originalText) {
+ lc = lastCompletion
+ }
+ if (lc == null) {
+ lastCompletion?.cancel(true)
+ val results = brigadierRoot.parseText.apply(sender to originalText)
+ lc = brigadierRoot.dispatcher.getCompletionSuggestions(results)
+ }
+ lastCompletion = lc
+ lastCompletionText = originalText
+ val suggestions = lastCompletion?.getNow(null) ?: return emptyList()
+ return suggestions.list.map { it.text }
+ }
+
+ override fun canCommandSenderUseCommand(sender: ICommandSender): Boolean {
+ return true // Permissions are checked by brigadier instead (or by the beforeCommand hook)
+ }
+
+}