use LiteralMeta instead of permission-less literal-names for subLiterals
All checks were successful
/ test (push) Successful in 3m22s
/ deploy (push) Successful in 1m18s

This commit is contained in:
kento2 2026-08-29 15:11:32 +02:00
parent 5fd408e69e
commit f18ce1c429
13 changed files with 68 additions and 40 deletions

View file

@ -1,11 +1,14 @@
package site.lab0x13.scrow.commands.bukkit;
import net.kyori.adventure.text.Component;
import org.jetbrains.annotations.Nullable;
import site.lab0x13.scrow.commands.PlatformAdapter;
class BukkitPlatform<C extends BukkitCommandContext<C>> implements PlatformAdapter<C> {
@Override
public boolean checkPermission(C ctx, String permission) {
public boolean checkPermission(C ctx, @Nullable String permission) {
if (permission == null)
return true;
return ctx.sender().hasPermission(permission);
}

View file

@ -1,11 +1,14 @@
package site.lab0x13.scrow.commands;
import site.lab0x13.scrow.commands.model.CommandContext;
import site.lab0x13.scrow.commands.model.literal.LiteralMeta;
import site.lab0x13.scrow.commands.model.literal.MessageStyle;
import site.lab0x13.scrow.commands.model.literal.RootLiteral;
import site.lab0x13.scrow.commands.parser.NodeTreeWalker;
import site.lab0x13.scrow.commands.parser.WalkResult;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.stream.Stream;
@ -42,15 +45,21 @@ public class CommandHandler<C extends CommandContext<C>> {
String input = null;
switch (walkResult) {
case WalkResult.LiteralUnknown<C> res -> {
stream = res.lastLiteral().subLiteralNames().stream();
stream = res.lastLiteral().subLiteralMetas().stream()
.filter(literalMeta -> platformAdapter.checkPermission(ctx, literalMeta.permission()))
.map(LiteralMeta::names)
.flatMap(Collection::stream);
input = res.input();
}
case WalkResult.LiteralExpected<C> res when trailingSpace ->
stream = res.lastLiteral().subLiteralMetas().stream()
.filter(literalMeta -> platformAdapter.checkPermission(ctx, literalMeta.permission()))
.map(LiteralMeta::names)
.flatMap(Collection::stream);
case WalkResult.ArgumentIllegal<C> res -> {
stream = res.arg().suggestionProvider().suggest(ctx, res.input()).stream();
input = res.input();
}
case WalkResult.LiteralExpected<C> res when trailingSpace ->
stream = res.lastLiteral().subLiteralNames().stream();
case WalkResult.ArgumentExpected<C> res when trailingSpace ->
stream = res.arg().suggestionProvider().suggest(ctx, "").stream();
default -> {

View file

@ -1,10 +1,11 @@
package site.lab0x13.scrow.commands;
import net.kyori.adventure.text.Component;
import org.jetbrains.annotations.Nullable;
public interface PlatformAdapter<C> {
boolean checkPermission(C ctx, String permission);
boolean checkPermission(C ctx, @Nullable String permission);
void sendMessage(C ctx, Component message);
}

View file

@ -11,7 +11,7 @@ import java.util.function.Supplier;
public final class DynamicLiteralBuilder<C extends CommandContext<C>> extends LiteralBuilder<C, DynamicLiteralBuilder<C>> {
private Supplier<List<String>> subLiteralNamesSupplier = Collections::emptyList;
private Supplier<List<LiteralMeta>> subLiteralMetaSupplier = Collections::emptyList;
private Function<String, @Nullable Literal<C>> subLiteralProvider = _ -> null;
DynamicLiteralBuilder(String... names) {
@ -23,6 +23,16 @@ public final class DynamicLiteralBuilder<C extends CommandContext<C>> extends Li
return this;
}
public DynamicLiteralBuilder<C> withSubLiteralNames(Supplier<List<LiteralMeta>> names) {
subLiteralMetaSupplier = names;
return this;
}
public DynamicLiteralBuilder<C> withSubLiteralProvider(Function<String, @Nullable Literal<C>> literalProvider) {
this.subLiteralProvider = literalProvider;
return this;
}
@Override
public Literal<C> build() {
return new DynamicLiteral<>(
@ -37,19 +47,9 @@ public final class DynamicLiteralBuilder<C extends CommandContext<C>> extends Li
}
@Override
public List<String> subLiteralNames() {
return subLiteralNamesSupplier.get();
public List<? extends LiteralMeta> subLiteralMetas() {
return subLiteralMetaSupplier.get();
}
};
}
public DynamicLiteralBuilder<C> withSubLiteralNames(Supplier<List<String>> names) {
subLiteralNamesSupplier = names;
return this;
}
public DynamicLiteralBuilder<C> withSubLiteralProvider(Function<String, @Nullable Literal<C>> literalProvider) {
this.subLiteralProvider = literalProvider;
return this;
}
}

View file

@ -7,12 +7,14 @@ import site.lab0x13.scrow.commands.model.Node;
import site.lab0x13.scrow.commands.model.SuggestionProvider;
import site.lab0x13.scrow.commands.model.argument.Argument;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
/**
* @param <C> argument of the command context
*/
public interface Literal<C extends CommandContext<C>> extends Node<C> {
public interface Literal<C extends CommandContext<C>> extends Node<C>, LiteralMeta {
static <C extends CommandContext<C>> StaticLiteralBuilder<C> builder(String... names) {
return new StaticLiteralBuilder<>(names);
@ -22,8 +24,6 @@ public interface Literal<C extends CommandContext<C>> extends Node<C> {
return new DynamicLiteralBuilder<>(names);
}
List<String> names();
@Nullable CommandExecutor<C> executor();
@Nullable Literal<C> getSubLiteral(String name);
@ -31,14 +31,15 @@ public interface Literal<C extends CommandContext<C>> extends Node<C> {
/**
* @return aliases/names of literals
*/
List<String> subLiteralNames();
List<? extends LiteralMeta> subLiteralMetas();
List<Argument<C, ?>> arguments();
String permission();
@Override
default SuggestionProvider<C> suggestionProvider() {
return (_, _) -> subLiteralNames();
return (_, _) -> subLiteralMetas().stream()
.map(LiteralMeta::names)
.flatMap(Collection::stream)
.toList();
}
}

View file

@ -0,0 +1,9 @@
package site.lab0x13.scrow.commands.model.literal;
import java.util.List;
public interface LiteralMeta {
List<String> names();
String permission();
}

View file

@ -37,8 +37,8 @@ public class RootLiteralWrapper<C extends CommandContext<C>> implements RootLite
}
@Override
public List<String> subLiteralNames() {
return literal.subLiteralNames();
public List<? extends LiteralMeta> subLiteralMetas() {
return literal.subLiteralMetas();
}
@Override

View file

@ -30,9 +30,7 @@ public class StaticLiteral<C extends CommandContext<C>> extends DynamicLiteral<C
}
@Override
public List<String> subLiteralNames() {
return subLiterals.stream()
.flatMap(literal -> literal.names().stream())
.toList();
public List<? extends LiteralMeta> subLiteralMetas() {
return subLiterals;
}
}

View file

@ -42,12 +42,12 @@ public class NodeTreeWalker<C extends CommandContext<C>> {
var nextLiteral = literal.getSubLiteral(token);
if (nextLiteral == null)
return new WalkResult.LiteralUnknown<>(ctx, literal, token);
if (nextLiteral.permission() != null && platformAdapter.checkPermission(ctx, nextLiteral.permission()))
if (platformAdapter.checkPermission(ctx, nextLiteral.permission()))
return new WalkResult.LiteralUnknown<>(ctx, literal, token);
literal = nextLiteral;
}
if (!literal.subLiteralNames().isEmpty()) {
if (!literal.subLiteralMetas().isEmpty()) {
var isOptional = literal.executor() != null;
return new WalkResult.LiteralExpected<>(ctx, literal, isOptional);
}

View file

@ -1,2 +1,2 @@
GROUP = "site.lab0x13.scrow"
VERSION = "1.2.0"
VERSION = "1.3.0"

View file

@ -10,11 +10,13 @@ public class ScrowCommands<C extends VelocityCommandContext<C>> implements IScro
private final ProxyServer server;
private final CommandContextFactory<C> commandContextFactory;
private final CommandHandler<C> commandHandler;
private final VelocityPlatform<C> platformAdapter;
public ScrowCommands(ProxyServer server, CommandContextFactory<C> commandContextFactory) {
this.server = server;
this.commandContextFactory = commandContextFactory;
this.commandHandler = new CommandHandler<C>(new VelocityPlatform<>());
this.platformAdapter = new VelocityPlatform<>();
this.commandHandler = new CommandHandler<>(platformAdapter);
}
public void register(RootLiteral<C> rootNode) {
@ -22,6 +24,6 @@ public class ScrowCommands<C extends VelocityCommandContext<C>> implements IScro
var meta = cm.metaBuilder(rootNode.names().getFirst())
.aliases(rootNode.names().stream().skip(1).toArray(String[]::new))
.build();
cm.register(meta, new VelocityCommand<>(commandHandler, commandContextFactory, rootNode));
cm.register(meta, new VelocityCommand<>(commandHandler, commandContextFactory, platformAdapter, rootNode));
}
}

View file

@ -2,6 +2,7 @@ package site.lab0x13.scrow.commands.velocity;
import com.velocitypowered.api.command.RawCommand;
import site.lab0x13.scrow.commands.CommandHandler;
import site.lab0x13.scrow.commands.PlatformAdapter;
import site.lab0x13.scrow.commands.model.literal.RootLiteral;
import java.util.Arrays;
@ -11,11 +12,13 @@ public class VelocityCommand<C extends VelocityCommandContext<C>> implements Raw
private final CommandHandler<C> commandHandler;
private final CommandContextFactory<C> commandContextFactory;
private final PlatformAdapter platformAdapter;
private final RootLiteral<C> rootLiteral;
public VelocityCommand(CommandHandler<C> commandHandler, CommandContextFactory<C> commandContextFactory, RootLiteral<C> rootLiteral) {
public VelocityCommand(CommandHandler<C> commandHandler, CommandContextFactory<C> commandContextFactory, PlatformAdapter platformAdapter, RootLiteral<C> rootLiteral) {
this.commandHandler = commandHandler;
this.commandContextFactory = commandContextFactory;
this.platformAdapter = platformAdapter;
this.rootLiteral = rootLiteral;
}
@ -29,8 +32,7 @@ public class VelocityCommand<C extends VelocityCommandContext<C>> implements Raw
@Override
public boolean hasPermission(Invocation ctx) {
if (rootLiteral.permission() == null) return true;
return ctx.source().hasPermission(rootLiteral.permission());
return platformAdapter.checkPermission(ctx, rootLiteral.permission());
}
@Override

View file

@ -1,11 +1,14 @@
package site.lab0x13.scrow.commands.velocity;
import net.kyori.adventure.text.Component;
import org.jetbrains.annotations.Nullable;
import site.lab0x13.scrow.commands.PlatformAdapter;
public class VelocityPlatform<C extends VelocityCommandContext<C>> implements PlatformAdapter<C> {
@Override
public boolean checkPermission(C ctx, String permission) {
public boolean checkPermission(C ctx, @Nullable String permission) {
if (permission == null)
return true;
return ctx.sender().hasPermission(permission);
}