mirror of
https://github.com/plexusorg/Plex.git
synced 2026-06-03 21:16:55 +00:00
Finish up Brigadier
This commit is contained in:
@@ -4,6 +4,12 @@ import dev.plex.command.PlexCommand;
|
||||
|
||||
/**
|
||||
* Registers and unregisters Plex commands with the running platform.
|
||||
*
|
||||
* <p>Commands are installed through Paper's Brigadier command lifecycle. A command
|
||||
* registered before that lifecycle event is active in the current server command
|
||||
* tree. A command registered or unregistered after that lifecycle event is staged
|
||||
* in Plex's registry and takes effect the next time Paper rebuilds lifecycle
|
||||
* commands, such as on a full server restart.</p>
|
||||
*/
|
||||
public interface CommandApi
|
||||
{
|
||||
@@ -17,7 +23,20 @@ public interface CommandApi
|
||||
/**
|
||||
* Unregisters a command from Plex.
|
||||
*
|
||||
* <p>If Paper's Brigadier lifecycle has already registered commands for this
|
||||
* server run, the command may remain in the active dispatcher until Paper
|
||||
* rebuilds lifecycle commands.</p>
|
||||
*
|
||||
* @param command command to unregister
|
||||
*/
|
||||
void unregister(PlexCommand command);
|
||||
|
||||
/**
|
||||
* Returns whether command changes are staged for the next Paper command
|
||||
* lifecycle rebuild.
|
||||
*
|
||||
* @return {@code true} when command registration or unregistration changed
|
||||
* after the active command lifecycle was built
|
||||
*/
|
||||
boolean requiresLifecycleReload();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
package dev.plex.command;
|
||||
|
||||
import dev.plex.command.source.RequiredCommandSource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Explicit metadata for a Plex command.
|
||||
*
|
||||
* @param name primary command name
|
||||
* @param description short command description
|
||||
* @param usage command usage text; {@code <command>} is replaced with the command name
|
||||
* @param aliases alternate root labels for the command
|
||||
* @param permission permission node required to use the command
|
||||
* @param requiredSource source restriction for command execution
|
||||
*/
|
||||
public record CommandSpec(
|
||||
String name,
|
||||
String description,
|
||||
String usage,
|
||||
List<String> aliases,
|
||||
String permission,
|
||||
RequiredCommandSource requiredSource)
|
||||
{
|
||||
/**
|
||||
* Creates a command spec builder for the given primary name.
|
||||
*
|
||||
* @param name primary command name
|
||||
* @return command spec builder
|
||||
*/
|
||||
public static Builder builder(String name)
|
||||
{
|
||||
return new Builder(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns usage text with the command placeholder expanded.
|
||||
*
|
||||
* @return command usage text for this command
|
||||
*/
|
||||
public String resolvedUsage()
|
||||
{
|
||||
return usage.replace("<command>", name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder for command specs.
|
||||
*/
|
||||
public static final class Builder
|
||||
{
|
||||
private final String name;
|
||||
private String description = "";
|
||||
private String usage = "/<command>";
|
||||
private List<String> aliases = List.of();
|
||||
private String permission = "";
|
||||
private RequiredCommandSource requiredSource = RequiredCommandSource.ANY;
|
||||
|
||||
private Builder(String name)
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the command description.
|
||||
*
|
||||
* @param description command description
|
||||
* @return this builder
|
||||
*/
|
||||
public Builder description(String description)
|
||||
{
|
||||
this.description = description;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the command usage text.
|
||||
*
|
||||
* @param usage command usage text
|
||||
* @return this builder
|
||||
*/
|
||||
public Builder usage(String usage)
|
||||
{
|
||||
this.usage = usage;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets comma-separated command aliases.
|
||||
*
|
||||
* @param aliases comma-separated command aliases
|
||||
* @return this builder
|
||||
*/
|
||||
public Builder aliases(String aliases)
|
||||
{
|
||||
if (aliases == null || aliases.isBlank())
|
||||
{
|
||||
this.aliases = List.of();
|
||||
return this;
|
||||
}
|
||||
this.aliases = Arrays.stream(aliases.split(","))
|
||||
.map(String::trim)
|
||||
.filter(alias -> !alias.isBlank())
|
||||
.toList();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets command aliases.
|
||||
*
|
||||
* @param aliases command aliases
|
||||
* @return this builder
|
||||
*/
|
||||
public Builder aliases(List<String> aliases)
|
||||
{
|
||||
this.aliases = aliases == null ? List.of() : new ArrayList<>(aliases);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the required permission node.
|
||||
*
|
||||
* @param permission permission node
|
||||
* @return this builder
|
||||
*/
|
||||
public Builder permission(String permission)
|
||||
{
|
||||
this.permission = permission == null ? "" : permission;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the required command source.
|
||||
*
|
||||
* @param requiredSource required command source
|
||||
* @return this builder
|
||||
*/
|
||||
public Builder source(RequiredCommandSource requiredSource)
|
||||
{
|
||||
this.requiredSource = requiredSource == null ? RequiredCommandSource.ANY : requiredSource;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the command spec.
|
||||
*
|
||||
* @return command spec
|
||||
*/
|
||||
public CommandSpec build()
|
||||
{
|
||||
return new CommandSpec(name, description, usage, List.copyOf(aliases), permission, requiredSource);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,8 @@
|
||||
package dev.plex.command;
|
||||
|
||||
import com.mojang.brigadier.tree.LiteralCommandNode;
|
||||
import dev.plex.command.annotation.CommandParameters;
|
||||
import dev.plex.command.annotation.CommandPermissions;
|
||||
import dev.plex.command.source.RequiredCommandSource;
|
||||
import io.papermc.paper.command.brigadier.CommandSourceStack;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -13,6 +10,13 @@ import java.util.List;
|
||||
*/
|
||||
public interface PlexCommand
|
||||
{
|
||||
/**
|
||||
* Returns explicit command metadata.
|
||||
*
|
||||
* @return command metadata
|
||||
*/
|
||||
CommandSpec commandSpec();
|
||||
|
||||
/**
|
||||
* Builds the Brigadier command tree for this command.
|
||||
*
|
||||
@@ -20,38 +24,6 @@ public interface PlexCommand
|
||||
*/
|
||||
LiteralCommandNode<CommandSourceStack> buildCommand();
|
||||
|
||||
/**
|
||||
* Reads command parameter metadata from {@link CommandParameters}.
|
||||
*
|
||||
* @return command parameter metadata
|
||||
* @throws IllegalStateException if the command class is missing {@link CommandParameters}
|
||||
*/
|
||||
default CommandParameters parameters()
|
||||
{
|
||||
CommandParameters parameters = getClass().getAnnotation(CommandParameters.class);
|
||||
if (parameters == null)
|
||||
{
|
||||
throw new IllegalStateException(getClass().getName() + " requires a CommandParameters annotation");
|
||||
}
|
||||
return parameters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads command permission metadata from {@link CommandPermissions}.
|
||||
*
|
||||
* @return command permission metadata
|
||||
* @throws IllegalStateException if the command class is missing {@link CommandPermissions}
|
||||
*/
|
||||
default CommandPermissions permissions()
|
||||
{
|
||||
CommandPermissions permissions = getClass().getAnnotation(CommandPermissions.class);
|
||||
if (permissions == null)
|
||||
{
|
||||
throw new IllegalStateException(getClass().getName() + " requires a CommandPermissions annotation");
|
||||
}
|
||||
return permissions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the primary command name.
|
||||
*
|
||||
@@ -59,7 +31,7 @@ public interface PlexCommand
|
||||
*/
|
||||
default String getName()
|
||||
{
|
||||
return parameters().name();
|
||||
return commandSpec().name();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -69,7 +41,7 @@ public interface PlexCommand
|
||||
*/
|
||||
default String getDescription()
|
||||
{
|
||||
return parameters().description();
|
||||
return commandSpec().description();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -79,7 +51,7 @@ public interface PlexCommand
|
||||
*/
|
||||
default String getUsage()
|
||||
{
|
||||
return parameters().usage().replace("<command>", getName());
|
||||
return commandSpec().resolvedUsage();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -89,7 +61,7 @@ public interface PlexCommand
|
||||
*/
|
||||
default String getPermission()
|
||||
{
|
||||
return permissions().permission();
|
||||
return commandSpec().permission();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -99,24 +71,16 @@ public interface PlexCommand
|
||||
*/
|
||||
default RequiredCommandSource getRequiredSource()
|
||||
{
|
||||
return permissions().source();
|
||||
return commandSpec().requiredSource();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns command aliases as a trimmed list.
|
||||
*
|
||||
* @return comma-separated aliases from {@link CommandParameters#aliases()} as a trimmed list
|
||||
* @return command aliases
|
||||
*/
|
||||
default List<String> getAliases()
|
||||
{
|
||||
String aliases = parameters().aliases();
|
||||
if (aliases.isBlank())
|
||||
{
|
||||
return List.of();
|
||||
}
|
||||
return Arrays.stream(aliases.split(","))
|
||||
.map(String::trim)
|
||||
.filter(alias -> !alias.isBlank())
|
||||
.toList();
|
||||
return commandSpec().aliases();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
package dev.plex.command.annotation;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
/**
|
||||
* Declares display and invocation metadata for a Plex command.
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface CommandParameters
|
||||
{
|
||||
/**
|
||||
* Returns the primary command name.
|
||||
*
|
||||
* @return primary command name
|
||||
*/
|
||||
String name();
|
||||
|
||||
/**
|
||||
* Returns the short command description.
|
||||
*
|
||||
* @return short command description
|
||||
*/
|
||||
String description() default "";
|
||||
|
||||
/**
|
||||
* Returns the command usage text.
|
||||
*
|
||||
* @return command usage text; {@code <command>} is replaced with the command name
|
||||
*/
|
||||
String usage() default "/<command>";
|
||||
|
||||
/**
|
||||
* Returns comma-separated command aliases.
|
||||
*
|
||||
* @return comma-separated command aliases
|
||||
*/
|
||||
String aliases() default "";
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package dev.plex.command.annotation;
|
||||
|
||||
import dev.plex.command.source.RequiredCommandSource;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
/**
|
||||
* Declares permission and command-source requirements for a Plex command.
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface CommandPermissions
|
||||
{
|
||||
/**
|
||||
* Returns the permission node required to use the command.
|
||||
*
|
||||
* @return permission node required to use the command
|
||||
*/
|
||||
String permission() default "";
|
||||
|
||||
/**
|
||||
* Returns the command source required to run the command.
|
||||
*
|
||||
* @return command source required to run the command
|
||||
*/
|
||||
RequiredCommandSource source() default RequiredCommandSource.ANY;
|
||||
}
|
||||
@@ -106,6 +106,13 @@ public abstract class PlexModule
|
||||
/**
|
||||
* Registers and tracks a command owned by this module.
|
||||
*
|
||||
* <p>Paper Brigadier commands are lifecycle-registered. Commands registered
|
||||
* during module load before Plex's command handler initializes are active for
|
||||
* the current startup. Commands registered after the Paper command lifecycle
|
||||
* has already run are tracked by Plex but are not guaranteed to appear in the
|
||||
* live dispatcher until Paper rebuilds lifecycle commands, normally on a full
|
||||
* server restart.</p>
|
||||
*
|
||||
* @param command command to register
|
||||
*/
|
||||
public void registerCommand(PlexCommand command)
|
||||
@@ -120,6 +127,10 @@ public abstract class PlexModule
|
||||
/**
|
||||
* Unregisters and stops tracking a command owned by this module.
|
||||
*
|
||||
* <p>Unregistration removes the command from this module and Plex's registry.
|
||||
* If Paper has already built the active Brigadier dispatcher, the command may
|
||||
* remain callable until Paper rebuilds lifecycle commands.</p>
|
||||
*
|
||||
* @param command command to unregister
|
||||
*/
|
||||
public void unregisterCommand(PlexCommand command)
|
||||
|
||||
Reference in New Issue
Block a user