Add support for case insensitive commands (/fIrM)
This commit is contained in:
@@ -63,7 +63,7 @@ runtime_optional = [
|
|||||||
"freecammod",
|
"freecammod",
|
||||||
"sodium",
|
"sodium",
|
||||||
"qolify",
|
"qolify",
|
||||||
"citresewn",
|
# "citresewn",
|
||||||
"ncr",
|
"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.arguments.ArgumentType
|
||||||
import com.mojang.brigadier.builder.ArgumentBuilder
|
import com.mojang.brigadier.builder.ArgumentBuilder
|
||||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder
|
|
||||||
import com.mojang.brigadier.builder.RequiredArgumentBuilder
|
import com.mojang.brigadier.builder.RequiredArgumentBuilder
|
||||||
import com.mojang.brigadier.context.CommandContext
|
import com.mojang.brigadier.context.CommandContext
|
||||||
import com.mojang.brigadier.suggestion.SuggestionProvider
|
import com.mojang.brigadier.suggestion.SuggestionProvider
|
||||||
@@ -32,9 +31,9 @@ operator fun <T : Any, C : CommandContext<*>> C.get(arg: TypeSafeArg<T>): T {
|
|||||||
|
|
||||||
fun literal(
|
fun literal(
|
||||||
name: String,
|
name: String,
|
||||||
block: LiteralArgumentBuilder<DefaultSource>.() -> Unit
|
block: CaseInsensitiveLiteralCommandNode.Builder<DefaultSource>.() -> Unit
|
||||||
): LiteralArgumentBuilder<DefaultSource> =
|
): CaseInsensitiveLiteralCommandNode.Builder<DefaultSource> =
|
||||||
LiteralArgumentBuilder.literal<DefaultSource>(name).also(block)
|
CaseInsensitiveLiteralCommandNode.Builder<DefaultSource>(name).also(block)
|
||||||
|
|
||||||
|
|
||||||
private fun normalizeGeneric(argument: Type): Class<*> {
|
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(
|
fun <T : ArgumentBuilder<DefaultSource, T>> T.thenLiteral(
|
||||||
name: String,
|
name: String,
|
||||||
block: LiteralArgumentBuilder<DefaultSource>.() -> Unit
|
block: CaseInsensitiveLiteralCommandNode.Builder<DefaultSource>.() -> Unit
|
||||||
): T =
|
): T =
|
||||||
then(literal(name, block))
|
then(literal(name, block))
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user