Add support for case insensitive commands (/fIrM)
This commit is contained in:
@@ -63,7 +63,7 @@ runtime_optional = [
|
||||
"freecammod",
|
||||
"sodium",
|
||||
"qolify",
|
||||
"citresewn",
|
||||
# "citresewn",
|
||||
"ncr",
|
||||
]
|
||||
|
||||
|
||||
29
src/main/java/moe/nea/firmament/mixins/MixinCommandNode.java
Normal file
29
src/main/java/moe/nea/firmament/mixins/MixinCommandNode.java
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Linnea Gräf <nea@nea.moe>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
package moe.nea.firmament.mixins;
|
||||
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
||||
import com.mojang.brigadier.tree.CommandNode;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
@Mixin(value = CommandNode.class, remap = false)
|
||||
public class MixinCommandNode<S> {
|
||||
@WrapOperation(method = "getRelevantNodes", at = @At(value = "INVOKE", target = "Ljava/util/Map;get(Ljava/lang/Object;)Ljava/lang/Object;"), remap = false)
|
||||
public Object modify(Map map, Object text, Operation<Object> op) {
|
||||
var original = op.call(map, text);
|
||||
if (original == null) {
|
||||
return map.get(((String) text).toLowerCase(Locale.ROOT));
|
||||
}
|
||||
return original;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Linnea Gräf <nea@nea.moe>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
package moe.nea.firmament.commands
|
||||
|
||||
import com.mojang.brigadier.Command
|
||||
import com.mojang.brigadier.RedirectModifier
|
||||
import com.mojang.brigadier.StringReader
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder
|
||||
import com.mojang.brigadier.context.CommandContextBuilder
|
||||
import com.mojang.brigadier.context.StringRange
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException
|
||||
import com.mojang.brigadier.tree.CommandNode
|
||||
import com.mojang.brigadier.tree.LiteralCommandNode
|
||||
import java.util.function.Predicate
|
||||
|
||||
class CaseInsensitiveLiteralCommandNode<S>(
|
||||
literal: String, command: Command<S>?, requirement: Predicate<S>?,
|
||||
redirect: CommandNode<S>?, modifier: RedirectModifier<S>?, forks: Boolean
|
||||
) : LiteralCommandNode<S>(
|
||||
literal.lowercase(), command, requirement, redirect, modifier, forks
|
||||
) {
|
||||
class Builder<S>(literal: String) : LiteralArgumentBuilder<S>(literal) {
|
||||
override fun build(): LiteralCommandNode<S> {
|
||||
val result = CaseInsensitiveLiteralCommandNode(
|
||||
literal,
|
||||
command, requirement, redirect, redirectModifier, isFork
|
||||
)
|
||||
for (argument in arguments) {
|
||||
result.addChild(argument)
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
override fun createBuilder(): LiteralArgumentBuilder<S> {
|
||||
return Builder<S>(literal).also {
|
||||
it.requires(requirement)
|
||||
it.forward(redirect, redirectModifier, isFork)
|
||||
if (command != null)
|
||||
it.executes(command)
|
||||
}
|
||||
}
|
||||
|
||||
override fun parse(reader: StringReader, contextBuilder: CommandContextBuilder<S>) {
|
||||
val start = reader.cursor
|
||||
val end = parse0(reader)
|
||||
if (end > -1) {
|
||||
contextBuilder.withNode(this, StringRange.between(start, end))
|
||||
return
|
||||
}
|
||||
|
||||
throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.literalIncorrect().createWithContext(reader, literal)
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "<iliteral $literal>"
|
||||
}
|
||||
|
||||
private fun parse0(reader: StringReader): Int {
|
||||
val start = reader.cursor
|
||||
if (reader.canRead(literal.length)) {
|
||||
val end = start + literal.length
|
||||
if (reader.string.substring(start, end).equals(literal, true)) {
|
||||
reader.cursor = end
|
||||
if (!reader.canRead() || reader.peek() == ' ') {
|
||||
return end
|
||||
} else {
|
||||
reader.cursor = start
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
}
|
||||
@@ -8,7 +8,6 @@ package moe.nea.firmament.commands
|
||||
|
||||
import com.mojang.brigadier.arguments.ArgumentType
|
||||
import com.mojang.brigadier.builder.ArgumentBuilder
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder
|
||||
import com.mojang.brigadier.builder.RequiredArgumentBuilder
|
||||
import com.mojang.brigadier.context.CommandContext
|
||||
import com.mojang.brigadier.suggestion.SuggestionProvider
|
||||
@@ -32,9 +31,9 @@ operator fun <T : Any, C : CommandContext<*>> C.get(arg: TypeSafeArg<T>): T {
|
||||
|
||||
fun literal(
|
||||
name: String,
|
||||
block: LiteralArgumentBuilder<DefaultSource>.() -> Unit
|
||||
): LiteralArgumentBuilder<DefaultSource> =
|
||||
LiteralArgumentBuilder.literal<DefaultSource>(name).also(block)
|
||||
block: CaseInsensitiveLiteralCommandNode.Builder<DefaultSource>.() -> Unit
|
||||
): CaseInsensitiveLiteralCommandNode.Builder<DefaultSource> =
|
||||
CaseInsensitiveLiteralCommandNode.Builder<DefaultSource>(name).also(block)
|
||||
|
||||
|
||||
private fun normalizeGeneric(argument: Type): Class<*> {
|
||||
@@ -101,7 +100,7 @@ fun <T : RequiredArgumentBuilder<DefaultSource, String>> T.suggestsList(provider
|
||||
|
||||
fun <T : ArgumentBuilder<DefaultSource, T>> T.thenLiteral(
|
||||
name: String,
|
||||
block: LiteralArgumentBuilder<DefaultSource>.() -> Unit
|
||||
block: CaseInsensitiveLiteralCommandNode.Builder<DefaultSource>.() -> Unit
|
||||
): T =
|
||||
then(literal(name, block))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user