Skip to content

Commit

Permalink
GH-498 Fabric command supports alias. Add an option to change the bri…
Browse files Browse the repository at this point in the history
…gadier input inspection display. (#498)

* fabric command supports alias

* Remove useless abstraction. Add an option to change the brigadier input inspection display.

* Add unit tests for keyed arguments.

---------

Co-authored-by: Rollczi <[email protected]>
  • Loading branch information
huanmeng-qwq and Rollczi authored Dec 22, 2024
1 parent fd19489 commit 47db6a8
Show file tree
Hide file tree
Showing 13 changed files with 109 additions and 94 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ public class ClientExampleFabric implements ClientModInitializer {
public void onInitializeClient() {
LiteFabricFactory.client()
.commands(new ClientCommands())
.settings(settings -> settings.inputInspectionDisplay("[....]"))
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.text.Text;

@Command(name = "litecommands")
@Command(name = "litecommands", aliases = "litecmd")
public class ClientCommands {

@Execute
Text info() {
return Text.of("Hello from LiteCommands!");
}

@Execute(name = "my")
@Execute(name = "my", aliases = "myName")
Text myName(@Sender FabricClientCommandSource sender) {
return sender.getPlayer().getName();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.Text;

@Command(name = "example")
@Command(name = "example", aliases = "tutorial")
public class ExampleCommand {
@Execute(name = "kick")
void sendMessage(@Arg("player") ServerPlayerEntity player, @Join("reason") String reason) {
player.networkHandler.disconnect(Text.of(reason));
}

@Execute(name = "message")
@Execute(name = "message", aliases = "msg")
Text sendMessage(@Quoted @Arg String message) {
return Text.of("You saied: " + message);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import java.lang.annotation.Annotation;
import java.lang.reflect.Executable;
import java.lang.reflect.Parameter;
import org.jetbrains.annotations.Nullable;

public abstract class ProfileAnnotationProcessor<SENDER, A extends Annotation, PROFILE extends ArgumentProfile<PROFILE>> implements AnnotationProcessor<SENDER> {

Expand Down Expand Up @@ -38,7 +39,7 @@ public AnnotationInvoker<SENDER> process(AnnotationInvoker<SENDER> invoker) {
});
}

protected abstract PROFILE createProfile(Parameter parameter, A annotation, Argument<?> argument);
protected abstract @Nullable PROFILE createProfile(Parameter parameter, A annotation, Argument<?> argument);

}

Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package dev.rollczi.litecommands.annotations.key;

import dev.rollczi.litecommands.annotations.argument.Arg;
import dev.rollczi.litecommands.annotations.argument.Key;
import dev.rollczi.litecommands.annotations.command.RootCommand;
import dev.rollczi.litecommands.annotations.execute.Execute;
import dev.rollczi.litecommands.argument.parser.ParseResult;
import dev.rollczi.litecommands.argument.parser.Parser;
import dev.rollczi.litecommands.unit.annotations.LiteTestSpec;
import org.junit.jupiter.api.Test;

class KeyCombinationsTest extends LiteTestSpec {

static class Faction {}

static LiteTestConfig config = builder -> builder
.argumentParser(Faction.class, Parser.of((invocation, text) -> ParseResult.success(new Faction())))
.advanced();

@RootCommand
static class TestCommand {

@Execute(name = "keyed")
void keyed(@Arg("arg-name") @Key("faction") Faction argValue) {}

@Execute(name = "undefined")
void undefined(@Arg("arg-name") Faction argValue) {}

}

@Test
void test() {
platform.execute("keyed factionValue")
.assertSuccess();

platform.execute("undefined factionValue")
.assertSuccess();
}

}
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
package dev.rollczi.litecommands.fabric;

import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.tree.LiteralCommandNode;
import dev.rollczi.litecommands.command.CommandRoute;
import dev.rollczi.litecommands.platform.AbstractPlatform;
import dev.rollczi.litecommands.platform.Platform;
import dev.rollczi.litecommands.platform.PlatformInvocationListener;
import dev.rollczi.litecommands.platform.PlatformSenderFactory;
import dev.rollczi.litecommands.platform.PlatformSettings;
import dev.rollczi.litecommands.platform.PlatformSuggestionListener;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

public abstract class FabricAbstractPlatform<SOURCE> extends AbstractPlatform<SOURCE, PlatformSettings> implements Platform<SOURCE, PlatformSettings> {
public abstract class FabricAbstractPlatform<SOURCE> extends AbstractPlatform<SOURCE, LiteFabricSettings> implements Platform<SOURCE, LiteFabricSettings> {

protected final Map<UUID, FabricAbstractCommand<SOURCE>> fabricCommands = new HashMap<>();
protected final Map<UUID, FabricCommand<SOURCE>> fabricCommands = new HashMap<>();

protected static boolean COMMAND_API_V2 = true;

Expand All @@ -26,13 +28,22 @@ public abstract class FabricAbstractPlatform<SOURCE> extends AbstractPlatform<SO
}
}

protected FabricAbstractPlatform(PlatformSettings settings, PlatformSenderFactory<SOURCE> factory) {
protected FabricAbstractPlatform(LiteFabricSettings settings, PlatformSenderFactory<SOURCE> factory) {
super(settings, factory);
registerEvents();
}

protected abstract void registerEvents();

protected void registerAllCommands(CommandDispatcher<SOURCE> dispatcher) {
for (FabricCommand<SOURCE> fabricCommand : fabricCommands.values()) {
LiteralCommandNode<SOURCE> commandNode = dispatcher.register(fabricCommand.toLiteral());
for (String alias : fabricCommand.getCommandRoute().getAliases()) {
dispatcher.register(LiteralArgumentBuilder.<SOURCE>literal(alias).redirect(commandNode));
}
}
}

@Override
protected void hook(CommandRoute<SOURCE> commandRoute, PlatformInvocationListener<SOURCE> invocationHook, PlatformSuggestionListener<SOURCE> suggestionHook) {
fabricCommands.put(commandRoute.getUniqueId(), createCommand(commandRoute, invocationHook, suggestionHook));
Expand All @@ -44,5 +55,8 @@ protected void unhook(CommandRoute<SOURCE> commandRoute) {
// TODO: unregister command from dispatcher
}

protected abstract FabricAbstractCommand<SOURCE> createCommand(CommandRoute<SOURCE> commandRoute, PlatformInvocationListener<SOURCE> invocationHook, PlatformSuggestionListener<SOURCE> suggestionHook);
protected FabricCommand<SOURCE> createCommand(CommandRoute<SOURCE> command, PlatformInvocationListener<SOURCE> invocationHook, PlatformSuggestionListener<SOURCE> suggestionHook) {
return new FabricCommand<>(this.getSenderFactory(), settings, command, invocationHook, suggestionHook);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import dev.rollczi.litecommands.invocation.Invocation;
import dev.rollczi.litecommands.platform.PlatformInvocationListener;
import dev.rollczi.litecommands.platform.PlatformSender;
import dev.rollczi.litecommands.platform.PlatformSenderFactory;
import dev.rollczi.litecommands.platform.PlatformSuggestionListener;
import dev.rollczi.litecommands.suggestion.Suggestion;
import dev.rollczi.litecommands.suggestion.SuggestionResult;
Expand All @@ -23,15 +24,17 @@
import java.util.List;
import java.util.concurrent.CompletableFuture;

public abstract class FabricAbstractCommand<SOURCE> {

private static final String FULL_ARGUMENTS = "[...]";
public class FabricCommand<SOURCE> {

private final PlatformSenderFactory<SOURCE> senderFactory;
private final LiteFabricSettings settings;
private final CommandRoute<SOURCE> baseRoute;
private final PlatformInvocationListener<SOURCE> invocationHook;
private final PlatformSuggestionListener<SOURCE> suggestionHook;

protected FabricAbstractCommand(CommandRoute<SOURCE> baseRoute, PlatformInvocationListener<SOURCE> invocationHook, PlatformSuggestionListener<SOURCE> suggestionHook) {
public FabricCommand(PlatformSenderFactory<SOURCE> senderFactory, LiteFabricSettings settings, CommandRoute<SOURCE> baseRoute, PlatformInvocationListener<SOURCE> invocationHook, PlatformSuggestionListener<SOURCE> suggestionHook) {
this.senderFactory = senderFactory;
this.settings = settings;
this.baseRoute = baseRoute;
this.invocationHook = invocationHook;
this.suggestionHook = suggestionHook;
Expand Down Expand Up @@ -64,15 +67,15 @@ private void appendRoute(LiteralArgumentBuilder<SOURCE> baseLiteral, CommandRout
@NotNull
private RequiredArgumentBuilder<SOURCE, String> createArguments() {
return RequiredArgumentBuilder
.<SOURCE, String>argument(FULL_ARGUMENTS, StringArgumentType.greedyString())
.<SOURCE, String>argument(settings.getInputInspectionDisplay(), StringArgumentType.greedyString())
.executes(context -> execute(context))
.suggests((context, builder) -> suggests(context, builder));
}

private int execute(CommandContext<SOURCE> context) {
RawCommand rawCommand = RawCommand.from(context.getInput());
ParseableInput<?> parseableInput = rawCommand.toParseableInput();
PlatformSender platformSender = createSender(context.getSource());
PlatformSender platformSender = this.senderFactory.create(context.getSource());
Invocation<SOURCE> invocation = new Invocation<>(context.getSource(), platformSender, baseRoute.getName(), rawCommand.getLabel(), parseableInput);

invocationHook.execute(invocation, parseableInput);
Expand All @@ -84,7 +87,7 @@ private int execute(CommandContext<SOURCE> context) {
String input = context.getInput();
RawCommand rawCommand = RawCommand.from(input);
SuggestionInput<?> suggestionInput = rawCommand.toSuggestionInput();
PlatformSender platformSender = createSender(context.getSource());
PlatformSender platformSender = this.senderFactory.create(context.getSource());
Invocation<SOURCE> invocation = new Invocation<>(context.getSource(), platformSender, baseRoute.getName(), rawCommand.getLabel(), suggestionInput);

SuggestionResult suggest = suggestionHook.suggest(invocation, suggestionInput);
Expand All @@ -108,5 +111,7 @@ Text tooltip(String string) {
return Text.literal(string);
}

protected abstract PlatformSender createSender(SOURCE source);
public CommandRoute<SOURCE> getCommandRoute() {
return baseRoute;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import dev.rollczi.litecommands.fabric.server.argument.PlayerArgument;
import dev.rollczi.litecommands.fabric.server.argument.WorldArgument;
import dev.rollczi.litecommands.message.MessageRegistry;
import dev.rollczi.litecommands.platform.PlatformSettings;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
Expand All @@ -33,20 +32,20 @@ private LiteFabricFactory() {
* @deprecated Use {@link LiteFabricFactory#builder()} instead
*/
@Deprecated
public static <B extends LiteCommandsBuilder<ServerCommandSource, PlatformSettings, B>> B create() {
public static <B extends LiteCommandsBuilder<ServerCommandSource, LiteFabricSettings, B>> B create() {
return builder();
}

/**
* @deprecated Use {@link LiteFabricFactory#server()} instead
*/
@Deprecated
public static <B extends LiteCommandsBuilder<ServerCommandSource, PlatformSettings, B>> B builder() {
public static <B extends LiteCommandsBuilder<ServerCommandSource, LiteFabricSettings, B>> B builder() {
return server();
}

@SuppressWarnings("unchecked")
public static <B extends LiteCommandsBuilder<ServerCommandSource, PlatformSettings, B>> B server() {
public static <B extends LiteCommandsBuilder<ServerCommandSource, LiteFabricSettings, B>> B server() {
return (B) LiteCommandsFactory.builder(ServerCommandSource.class, new FabricServerPlatform(new LiteFabricSettings()))
.self((builder, internal) -> {
MessageRegistry<ServerCommandSource> messages = internal.getMessageRegistry();
Expand All @@ -67,7 +66,7 @@ public static <B extends LiteCommandsBuilder<ServerCommandSource, PlatformSettin

@SuppressWarnings("unchecked")
@Environment(EnvType.CLIENT)
public static <B extends LiteCommandsBuilder<FabricClientCommandSource, PlatformSettings, B>> B client() {
public static <B extends LiteCommandsBuilder<FabricClientCommandSource, LiteFabricSettings, B>> B client() {
return (B) LiteCommandsFactory.builder(FabricClientCommandSource.class, new FabricClientPlatform(new LiteFabricSettings()))
.self((builder, internal) -> {
MessageRegistry<FabricClientCommandSource> messages = internal.getMessageRegistry();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,25 @@
package dev.rollczi.litecommands.fabric;

import dev.rollczi.litecommands.platform.PlatformSettings;
import org.jetbrains.annotations.ApiStatus;

public class LiteFabricSettings implements PlatformSettings {

private String inputInspectionDisplay = "[...]";

String getInputInspectionDisplay() {
return this.inputInspectionDisplay;
}

/**
* The name of the brigadier argument used to inspection, default is "[...]".
* Inspection sometimes displays while the player is typing the command.
* LiteCommands don't support brigadier suggestions, but we must provide a name for the default input argument.
*/
@ApiStatus.Experimental
public LiteFabricSettings inputInspectionDisplay(String name) {
this.inputInspectionDisplay = name;
return this;
}

}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
package dev.rollczi.litecommands.fabric.client;

import dev.rollczi.litecommands.command.CommandRoute;
import dev.rollczi.litecommands.fabric.FabricAbstractCommand;
import dev.rollczi.litecommands.fabric.FabricAbstractPlatform;
import dev.rollczi.litecommands.platform.PlatformInvocationListener;
import dev.rollczi.litecommands.platform.PlatformSettings;
import dev.rollczi.litecommands.platform.PlatformSuggestionListener;
import dev.rollczi.litecommands.fabric.LiteFabricSettings;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback;
Expand All @@ -14,7 +10,7 @@
@Environment(EnvType.CLIENT)
public class FabricClientPlatform extends FabricAbstractPlatform<FabricClientCommandSource> {

public FabricClientPlatform(PlatformSettings settings) {
public FabricClientPlatform(LiteFabricSettings settings) {
super(settings, source -> new FabricClientSender(source));
}

Expand All @@ -24,14 +20,8 @@ protected void registerEvents() {
throw new UnsupportedOperationException("The current 'fabric-api' does not include fabric-command-api-v2. Please update 'fabric-api'");
}
ClientCommandRegistrationCallback.EVENT.register((dispatcher, commandRegistryAccess) -> {
for (FabricAbstractCommand<FabricClientCommandSource> fabricCommand : fabricCommands.values()) {
dispatcher.register(fabricCommand.toLiteral());
}
this.registerAllCommands(dispatcher);
});
}

@Override
protected FabricAbstractCommand<FabricClientCommandSource> createCommand(CommandRoute<FabricClientCommandSource> commandRoute, PlatformInvocationListener<FabricClientCommandSource> invocationHook, PlatformSuggestionListener<FabricClientCommandSource> suggestionHook) {
return new FabricClientCommand(commandRoute, invocationHook, suggestionHook);
}
}

This file was deleted.

Loading

0 comments on commit 47db6a8

Please sign in to comment.