refactor: change approach with <1.20.6 Paper commands

Fixes issues with custom arg types on Paper
dependabot/gradle/org.projectlombok-lombok-1.18.34 1.1.5
William 5 months ago
parent 1e7297c0b3
commit d399788b9f
No known key found for this signature in database

@ -1,4 +1,4 @@
name: UniformExample name: UniformExample
version: 1.0 version: "1.0"
api-version: "1.19" api-version: "1.20"
main: net.william278.uniform.UniformExample main: net.william278.uniform.UniformExample

@ -3,6 +3,6 @@ javaVersion=17
org.gradle.jvmargs='-Dfile.encoding=UTF-8' org.gradle.jvmargs='-Dfile.encoding=UTF-8'
org.gradle.daemon=true org.gradle.daemon=true
library_version=1.1.4 library_version=1.1.5
library_archive=uniform library_archive=uniform
library_description=Cross-platform wrapper for making Brigadier commands, based on BrigadierWrapper by Tofaa2, itself inspired by emortalmcs command system. library_description=Cross-platform wrapper for making Brigadier commands, based on BrigadierWrapper by Tofaa2, itself inspired by emortalmcs command system.

@ -21,82 +21,106 @@
package net.william278.uniform.paper; package net.william278.uniform.paper;
import com.destroystokyo.paper.brigadier.BukkitBrigadierCommandSource; import com.mojang.brigadier.CommandDispatcher;
import com.destroystokyo.paper.event.brigadier.CommandRegisteredEvent; import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.google.common.collect.Sets; import com.mojang.brigadier.suggestion.Suggestion;
import com.mojang.brigadier.builder.LiteralArgumentBuilder; import net.kyori.adventure.text.Component;
import com.mojang.brigadier.tree.LiteralCommandNode; import net.kyori.adventure.text.format.NamedTextColor;
import lombok.AllArgsConstructor;
import net.william278.uniform.BaseCommand; import net.william278.uniform.BaseCommand;
import net.william278.uniform.Command; import net.william278.uniform.Command;
import net.william278.uniform.CommandUser; import net.william278.uniform.CommandUser;
import net.william278.uniform.Uniform; import net.william278.uniform.Uniform;
import org.bukkit.event.EventHandler; import org.bukkit.command.CommandException;
import org.bukkit.event.Listener; import org.bukkit.command.CommandSender;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.function.Function; import java.util.function.Function;
@SuppressWarnings({"removal", "deprecation", "UnstableApiUsage"}) @SuppressWarnings("unused")
public class LegacyPaperCommand extends BaseCommand<BukkitBrigadierCommandSource> { public class LegacyPaperCommand extends BaseCommand<CommandSender> {
static final Function<Object, CommandUser> USER_SUPPLIER = (user) -> new LegacyPaperCommandUser( static final Function<Object, CommandUser> USER_SUPPLIER = (user) -> new LegacyPaperCommandUser(
(BukkitBrigadierCommandSource) user (CommandSender) user
); );
public LegacyPaperCommand(@NotNull Command command) { public LegacyPaperCommand(@NotNull Command command) {
super(command); super(command);
} }
public LegacyPaperCommand(@NotNull String name, @NotNull String description, @NotNull List<String> aliases) {
super(name, description, aliases);
}
public LegacyPaperCommand(@NotNull String name, @NotNull List<String> aliases) { public LegacyPaperCommand(@NotNull String name, @NotNull List<String> aliases) {
super(name, aliases); super(name, aliases);
} }
public LegacyPaperCommand(@NotNull String name, @NotNull String description, @NotNull List<String> aliases) { @NotNull
super(name, description, aliases); Impl getImpl(@NotNull Uniform uniform) {
return new Impl(uniform, this);
} }
@Override static final class Impl extends org.bukkit.command.Command {
public void addSubCommand(@NotNull Command command) {
addSubCommand(new LegacyPaperCommand(command)); private static final int COMMAND_SUCCESS = com.mojang.brigadier.Command.SINGLE_SUCCESS;
private final CommandDispatcher<CommandSender> dispatcher = new CommandDispatcher<>();
public Impl(@NotNull Uniform uniform, @NotNull LegacyPaperCommand command) {
super(command.getName());
this.dispatcher.register(command.createBuilder());
this.setDescription(command.getDescription());
this.setAliases(command.getAliases());
} }
@SuppressWarnings("deprecation")
@Override @Override
public Uniform getUniform() { public boolean execute(@NotNull CommandSender commandSender, @NotNull String alias, @NotNull String[] args) {
return PaperUniform.INSTANCE; try {
return dispatcher.execute(getInput(args), commandSender) == COMMAND_SUCCESS;
} catch (CommandSyntaxException e) {
commandSender.sendMessage(Component
.translatable("command.context.parse_error", NamedTextColor.RED)
.args(
Component.text(e.getRawMessage().getString()),
Component.text(e.getCursor()),
Component.text(e.getContext())
));
return false;
} catch (CommandException e) {
commandSender.sendMessage(Component.text(e.getMessage(), NamedTextColor.RED));
return false;
}
} }
@AllArgsConstructor
static class Registrar implements Listener {
@NotNull @NotNull
private final JavaPlugin plugin; @Override
public List<String> tabComplete(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args)
throws IllegalArgumentException {
final String passed = getInput(args);
return dispatcher.getCompletionSuggestions(
dispatcher.parse(passed, sender),
passed.length() // Spigot API limitation - we can only TAB complete the full text length :(
)
.thenApply(suggestions -> suggestions.getList().stream().map(Suggestion::getText).toList())
.join();
}
@NotNull @NotNull
private final Set<LegacyPaperCommand> commands; private String getInput(@NotNull String[] args) {
return args.length == 0 ? getName() : "%s %s".formatted(getName(), String.join(" ", args));
@EventHandler }
public void commandRegisterEvent(CommandRegisteredEvent<BukkitBrigadierCommandSource> event) {
commands.forEach(command -> {
// Register root command
final LiteralCommandNode<BukkitBrigadierCommandSource> built = command.build();
event.getRoot().addChild(built);
// Register aliases
final String namespace = plugin.getName().toLowerCase(Locale.ENGLISH).replaceAll("[^a-z0-9_-]", "");
final Set<String> aliases = Sets.newHashSet(command.getAliases());
command.getAliases().forEach(a -> aliases.add(namespace + ":" + a));
aliases.add(namespace + ":" + command.getName());
aliases.forEach(alias -> event.getRoot().addChild(
LiteralArgumentBuilder.<BukkitBrigadierCommandSource>literal(alias)
.requires(built.getRequirement()).executes(built.getCommand()).redirect(built)
.build()
));
});
commands.clear();
} }
@Override
public void addSubCommand(@NotNull Command command) {
addSubCommand(new LegacyPaperCommand(command));
}
@Override
public Uniform getUniform() {
return PaperUniform.INSTANCE;
} }
} }

@ -21,44 +21,43 @@
package net.william278.uniform.paper; package net.william278.uniform.paper;
import com.destroystokyo.paper.brigadier.BukkitBrigadierCommandSource;
import net.kyori.adventure.audience.Audience; import net.kyori.adventure.audience.Audience;
import net.william278.uniform.CommandUser; import net.william278.uniform.CommandUser;
import net.william278.uniform.Permission; import net.william278.uniform.Permission;
import org.bukkit.command.CommandSender;
import org.bukkit.command.ConsoleCommandSender; import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.UUID; import java.util.UUID;
@SuppressWarnings("removal") public record LegacyPaperCommandUser(@NotNull CommandSender sender) implements CommandUser {
public record LegacyPaperCommandUser(@NotNull BukkitBrigadierCommandSource source) implements CommandUser {
@Override @Override
@NotNull @NotNull
public Audience getAudience() { public Audience getAudience() {
return source.getBukkitSender(); return sender;
} }
@Override @Override
@Nullable
public String getName() { public String getName() {
return source.getBukkitEntity() != null ? source.getBukkitEntity().getName() : null; return sender.getName();
} }
@Override @Override
@Nullable @Nullable
public UUID getUuid() { public UUID getUuid() {
return source.getBukkitEntity() != null ? source.getBukkitEntity().getUniqueId() : null; return sender instanceof Player player ? player.getUniqueId() : null;
} }
@Override @Override
public boolean checkPermission(@NotNull Permission permission) { public boolean checkPermission(@NotNull Permission permission) {
if (source.getBukkitSender().isPermissionSet(permission.node())) { if (sender.isPermissionSet(permission.node())) {
return source.getBukkitSender().hasPermission(permission.node()); return sender.hasPermission(permission.node());
} }
return permission.defaultValue().check( return permission.defaultValue().check(
source.getBukkitSender().isOp() || source.getBukkitSender() instanceof ConsoleCommandSender sender.isOp() || sender instanceof ConsoleCommandSender
); );
} }

@ -32,8 +32,10 @@ import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.Arrays; import java.util.Arrays;
import java.util.Locale;
import java.util.Set; import java.util.Set;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Stream;
/** /**
* A class for registering commands with the Paper server's command manager * A class for registering commands with the Paper server's command manager
@ -44,27 +46,23 @@ public final class PaperUniform implements Uniform {
static PaperUniform INSTANCE; static PaperUniform INSTANCE;
private final Set<LegacyPaperCommand> legacyCommands = Sets.newHashSet();
private final Set<PaperCommand> commands = Sets.newHashSet(); private final Set<PaperCommand> commands = Sets.newHashSet();
private final boolean useModernApi = isUseModernApi(); private final boolean useModernApi = isUseModernApi();
private final JavaPlugin plugin;
@Getter @Getter
@Setter @Setter
Function<Object, CommandUser> commandUserSupplier; Function<Object, CommandUser> commandUserSupplier;
private PaperUniform(@NotNull JavaPlugin plugin) { private PaperUniform(@NotNull JavaPlugin plugin) {
this.plugin = plugin;
// Modern (1.20.6+) Lifecycle event based Paper Brigadier API // Modern (1.20.6+) Lifecycle event based Paper Brigadier API
if (useModernApi) { if (useModernApi) {
this.commandUserSupplier = PaperCommand.USER_SUPPLIER; this.commandUserSupplier = PaperCommand.USER_SUPPLIER;
PaperCommand.register(plugin, commands); PaperCommand.register(plugin, commands);
return; return;
} }
// Legacy (1.17-1.20.4) event-based Paper Brigadier API
this.commandUserSupplier = LegacyPaperCommand.USER_SUPPLIER; this.commandUserSupplier = LegacyPaperCommand.USER_SUPPLIER;
plugin.getServer().getPluginManager().registerEvents(
new LegacyPaperCommand.Registrar(plugin, legacyCommands), plugin
);
} }
/** /**
@ -100,13 +98,18 @@ public final class PaperUniform implements Uniform {
@SafeVarargs @SafeVarargs
@Override @Override
public final <S, T extends BaseCommand<S>> void register(T... commands) { public final <S, T extends BaseCommand<S>> void register(T... commands) {
Arrays.stream(commands).forEach(c -> { // Mark as to be registered with modern API
final Stream<T> s = Arrays.stream(commands);
if (useModernApi) { if (useModernApi) {
this.commands.add((PaperCommand) c); s.forEach(c -> this.commands.add((PaperCommand) c));
} else { return;
this.legacyCommands.add((LegacyPaperCommand) c);
} }
});
// Register with the legacy API
plugin.getServer().getCommandMap().registerAll(
plugin.getName().toLowerCase(Locale.ENGLISH).replaceAll("[^a-z0-9_]", ""),
s.map(c -> (LegacyPaperCommand) c).map(c -> (org.bukkit.command.Command) c.getImpl(this)).toList()
);
} }
/** /**

Loading…
Cancel
Save