Cleanup builtin and extension command implementations

This commit is contained in:
Konicai 2023-09-01 20:06:37 -04:00
parent 47031ce283
commit cddc34aeb7
No known key found for this signature in database
GPG Key ID: 710D09287708C823
16 changed files with 138 additions and 147 deletions

View File

@ -26,6 +26,7 @@
package org.geysermc.geyser.api.command;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.geyser.api.GeyserApi;
import org.geysermc.geyser.api.connection.GeyserConnection;
import org.geysermc.geyser.api.extension.Extension;
@ -64,9 +65,9 @@ public interface Command {
String permission();
/**
* Gets the aliases for this command.
* Gets the aliases for this command, as an unmodifiable list
*
* @return the aliases for this command
* @return the aliases for this command as an unmodifiable list
*/
@NonNull
List<String> aliases();
@ -91,7 +92,7 @@ public interface Command {
}
/**
* Used to send a deny message to Java players if this command can only be used by Bedrock players.
* Used to send a deny-message to Java players if this command can only be used by Bedrock players.
*
* @return true if this command can only be used by Bedrock players.
*/
@ -152,7 +153,7 @@ public interface Command {
* @param description the command description
* @return the builder
*/
Builder<T> description(@NonNull String description);
Builder<T> description(@Nullable String description);
/**
* Sets the permission node.
@ -160,7 +161,7 @@ public interface Command {
* @param permission the permission node
* @return the builder
*/
Builder<T> permission(@NonNull String permission);
Builder<T> permission(@Nullable String permission);
/**
* Sets the aliases.
@ -168,7 +169,7 @@ public interface Command {
* @param aliases the aliases
* @return the builder
*/
Builder<T> aliases(@NonNull List<String> aliases);
Builder<T> aliases(@Nullable List<String> aliases);
/**
* Sets if this command is designed to be used only by server operators.
@ -176,6 +177,7 @@ public interface Command {
* @param suggestedOpOnly if this command is designed to be used only by server operators
* @return the builder
*/
@Deprecated(forRemoval = true)
Builder<T> suggestedOpOnly(boolean suggestedOpOnly);
/**

View File

@ -27,8 +27,8 @@ package org.geysermc.geyser.command;
import cloud.commandframework.CommandManager;
import cloud.commandframework.arguments.standard.StringArgument;
import lombok.RequiredArgsConstructor;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.api.command.Command;
import org.geysermc.geyser.api.command.CommandExecutor;
@ -37,44 +37,53 @@ import org.geysermc.geyser.api.extension.Extension;
import org.geysermc.geyser.extension.command.GeyserExtensionCommand;
import org.geysermc.geyser.session.GeyserSession;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
@RequiredArgsConstructor
public class CommandBuilder<T extends CommandSource> implements Command.Builder<T> {
private final Extension extension;
private Class<? extends T> sourceType;
private String name;
private String description = "";
private String permission = "";
private String description;
private String permission;
private List<String> aliases;
private boolean suggestedOpOnly = false;
private boolean suggestedOpOnly = false; // deprecated for removal
private boolean executableOnConsole = true;
private boolean bedrockOnly;
private boolean bedrockOnly = false;
private CommandExecutor<T> executor;
public CommandBuilder(Extension extension) {
this.extension = Objects.requireNonNull(extension);
}
@Override
public Command.Builder<T> source(@NonNull Class<? extends T> sourceType) {
this.sourceType = sourceType;
return this;
}
@Override
public CommandBuilder<T> name(@NonNull String name) {
this.name = name;
return this;
}
public CommandBuilder<T> description(@NonNull String description) {
@Override
public CommandBuilder<T> description(@Nullable String description) {
this.description = description;
return this;
}
public CommandBuilder<T> permission(@NonNull String permission) {
@Override
public CommandBuilder<T> permission(@Nullable String permission) {
this.permission = permission;
return this;
}
public CommandBuilder<T> aliases(@NonNull List<String> aliases) {
@Override
public CommandBuilder<T> aliases(@Nullable List<String> aliases) {
this.aliases = aliases;
return this;
}
@ -85,32 +94,39 @@ public class CommandBuilder<T extends CommandSource> implements Command.Builder<
return this;
}
@Override
public CommandBuilder<T> executableOnConsole(boolean executableOnConsole) {
this.executableOnConsole = executableOnConsole;
return this;
}
@Override
public CommandBuilder<T> bedrockOnly(boolean bedrockOnly) {
this.bedrockOnly = bedrockOnly;
return this;
}
@Override
public CommandBuilder<T> executor(@NonNull CommandExecutor<T> executor) {
this.executor = executor;
return this;
}
@NonNull
@Override
public GeyserExtensionCommand build() {
if (this.name == null || this.name.isBlank()) {
throw new IllegalArgumentException("Command cannot be null or blank!");
final Class<? extends T> sourceType = this.sourceType;
final boolean suggestedOpOnly = this.suggestedOpOnly;
final CommandExecutor<T> executor = this.executor;
if (sourceType == null) {
throw new IllegalArgumentException("Source type was not defined for command " + name + " in extension " + extension.name());
}
if (executor == null) {
throw new IllegalArgumentException("Command executor was not defined for command " + name + " in extension " + extension.name());
}
if (this.sourceType == null) {
throw new IllegalArgumentException("Source type was not defined for command " + this.name + " in extension " + this.extension.name());
}
return new GeyserExtensionCommand(this.extension, this.name, this.description, this.permission) {
GeyserExtensionCommand command = new GeyserExtensionCommand(extension, name, description, permission, executableOnConsole, bedrockOnly) {
@SuppressWarnings("unchecked")
@Override
@ -121,9 +137,6 @@ public class CommandBuilder<T extends CommandSource> implements Command.Builder<
GeyserCommandSource source = context.getSender();
String[] args = context.getOrDefault("args", "").split(" ");
Class<? extends T> sourceType = CommandBuilder.this.sourceType;
CommandExecutor<T> executor = CommandBuilder.this.executor;
if (sourceType.isInstance(source)) {
executor.execute((T) source, this, args);
return;
@ -135,35 +148,18 @@ public class CommandBuilder<T extends CommandSource> implements Command.Builder<
return;
}
// todo: send sender message instead
GeyserImpl.getInstance().getLogger().debug("Ignoring command " + this.name + " due to no suitable sender.");
});
}
@NonNull
@Override
public List<String> aliases() {
return CommandBuilder.this.aliases == null ? Collections.emptyList() : CommandBuilder.this.aliases;
}
@Override
public boolean isSuggestedOpOnly() {
return CommandBuilder.this.suggestedOpOnly;
}
@Override
public boolean isExecutableOnConsole() {
return CommandBuilder.this.executableOnConsole;
}
@Override
public boolean isBedrockOnly() {
return CommandBuilder.this.bedrockOnly;
}
@Override
public String rootCommand() {
return extension().rootCommand();
return suggestedOpOnly;
}
};
command.aliases = aliases != null ? new ArrayList<>(aliases) : Collections.emptyList();
return command;
}
}

View File

@ -28,18 +28,13 @@ package org.geysermc.geyser.command;
import cloud.commandframework.Command;
import cloud.commandframework.CommandManager;
import cloud.commandframework.meta.CommandMeta;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import lombok.experimental.Accessors;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.jetbrains.annotations.Contract;
import java.util.Collections;
import java.util.List;
@Accessors(fluent = true)
@Getter
@RequiredArgsConstructor
public abstract class GeyserCommand implements org.geysermc.geyser.api.command.Command {
/**
@ -52,15 +47,77 @@ public abstract class GeyserCommand implements org.geysermc.geyser.api.command.C
*/
public static final CommandMeta.Key<Boolean> PLAYER_ONLY = CommandMeta.Key.of(Boolean.class, "player-only", meta -> false);
@NonNull
protected final String name;
/**
* The description of the command - will attempt to be translated.
*/
@NonNull
protected final String description;
@NonNull
protected final String permission;
@Setter
private List<String> aliases = Collections.emptyList();
protected final boolean executableOnConsole;
protected final boolean bedrockOnly;
protected List<String> aliases = Collections.emptyList();
public GeyserCommand(@NonNull String name, @Nullable String description, @Nullable String permission, boolean executableOnConsole, boolean bedrockOnly) {
if (name == null || name.isBlank()) {
throw new IllegalArgumentException("Command cannot be null or blank!");
}
this.name = name;
this.description = description != null ? description : "";
this.permission = permission != null ? permission : "";
if (bedrockOnly && executableOnConsole) {
throw new IllegalArgumentException("Command cannot be both bedrockOnly and executableOnConsole");
}
this.executableOnConsole = executableOnConsole;
this.bedrockOnly = bedrockOnly;
}
public GeyserCommand(@NonNull String name, @NonNull String description, @Nullable String permission) {
this(name, description, permission, true, false);
}
@NonNull
@Override
public final String name() {
return name;
}
@NonNull
@Override
public final String description() {
return description;
}
@NonNull
@Override
public final String permission() {
return permission;
}
@Override
public final boolean isExecutableOnConsole() {
return executableOnConsole;
}
@Override
public final boolean isBedrockOnly() {
return bedrockOnly;
}
@NonNull
@Override
public final List<String> aliases() {
return Collections.unmodifiableList(aliases);
}
public String rootCommand() {
return "geyser";

View File

@ -33,8 +33,9 @@ import org.geysermc.geyser.text.ChatColor;
import org.geysermc.geyser.text.MinecraftLocale;
public class AdvancedTooltipsCommand extends GeyserCommand {
public AdvancedTooltipsCommand(String name, String description, String permission) {
super(name, description, permission);
super(name, description, permission, false, true);
}
@Override
@ -50,14 +51,4 @@ public class AdvancedTooltipsCommand extends GeyserCommand {
session.getInventoryTranslator().updateInventory(session, session.getPlayerInventory());
}));
}
@Override
public boolean isExecutableOnConsole() {
return false;
}
@Override
public boolean isBedrockOnly() {
return true;
}
}

View File

@ -31,8 +31,9 @@ import org.geysermc.geyser.command.GeyserCommand;
import org.geysermc.geyser.command.GeyserCommandSource;
public class AdvancementsCommand extends GeyserCommand {
public AdvancementsCommand(String name, String description, String permission) {
super(name, description, permission);
super(name, description, permission, false, true);
}
@Override
@ -42,14 +43,4 @@ public class AdvancementsCommand extends GeyserCommand {
context.getSender().connection().ifPresent(session ->
session.getAdvancementsCache().buildAndShowMenuForm()));
}
@Override
public boolean isExecutableOnConsole() {
return false;
}
@Override
public boolean isBedrockOnly() {
return true;
}
}

View File

@ -132,9 +132,4 @@ public class ConnectionTestCommand extends GeyserCommand {
"https://wiki.geysermc.org/geyser/supported-hosting-providers/" + ", see this page: "
+ "https://wiki.geysermc.org/geyser/fixing-unable-to-connect-to-world/" + ", or contact us on our Discord: " + "https://discord.gg/geysermc");
}
@Override
public boolean isSuggestedOpOnly() {
return true;
}
}

View File

@ -152,9 +152,4 @@ public class DumpCommand extends GeyserCommand {
geyser.getLogger().info(GeyserLocale.getLocaleStringLog("geyser.commands.dump.created", source.name(), uploadedDumpUrl));
}
}
@Override
public boolean isSuggestedOpOnly() {
return true;
}
}

View File

@ -49,7 +49,7 @@ public class HelpCommand extends GeyserCommand {
this.baseCommand = baseCommand;
this.commands = commands.values();
this.aliases(Collections.singletonList("?"));
this.aliases = Collections.singletonList("?");
}
@Override

View File

@ -58,9 +58,4 @@ public class ListCommand extends GeyserCommand {
source.sendMessage(message);
});
}
@Override
public boolean isSuggestedOpOnly() {
return true;
}
}

View File

@ -35,7 +35,7 @@ import org.geysermc.geyser.session.GeyserSession;
public class OffhandCommand extends GeyserCommand {
public OffhandCommand(GeyserImpl geyser, String name, String description, String permission) {
super(name, description, permission);
super(name, description, permission, false, true);
}
@Override
@ -43,14 +43,4 @@ public class OffhandCommand extends GeyserCommand {
return super.builder(manager)
.handler(context -> context.getSender().connection().ifPresent(GeyserSession::requestOffhandSwap));
}
@Override
public boolean isExecutableOnConsole() {
return false;
}
@Override
public boolean isBedrockOnly() {
return true;
}
}

View File

@ -52,9 +52,4 @@ public class ReloadCommand extends GeyserCommand {
geyser.reload();
});
}
@Override
public boolean isSuggestedOpOnly() {
return true;
}
}

View File

@ -33,8 +33,9 @@ import org.geysermc.geyser.command.GeyserCommandSource;
import org.geysermc.geyser.util.SettingsUtils;
public class SettingsCommand extends GeyserCommand {
public SettingsCommand(GeyserImpl geyser, String name, String description, String permission) {
super(name, description, permission);
super(name, description, permission, false, true);
}
@Override
@ -44,14 +45,4 @@ public class SettingsCommand extends GeyserCommand {
context.getSender().connection().ifPresent(session ->
session.sendForm(SettingsUtils.buildForm(session))));
}
@Override
public boolean isExecutableOnConsole() {
return false;
}
@Override
public boolean isBedrockOnly() {
return true;
}
}

View File

@ -36,7 +36,7 @@ import org.geysermc.geyser.command.GeyserCommandSource;
public class StatisticsCommand extends GeyserCommand {
public StatisticsCommand(GeyserImpl geyser, String name, String description, String permission) {
super(name, description, permission);
super(name, description, permission, false, true);
}
@Override
@ -48,14 +48,4 @@ public class StatisticsCommand extends GeyserCommand {
session.sendDownstreamPacket(packet);
}));
}
@Override
public boolean isExecutableOnConsole() {
return false;
}
@Override
public boolean isBedrockOnly() {
return true;
}
}

View File

@ -41,7 +41,7 @@ public class StopCommand extends GeyserCommand {
super(name, description, permission);
this.geyser = geyser;
this.aliases(Collections.singletonList("shutdown"));
this.aliases = Collections.singletonList("shutdown");
}
@Override
@ -49,9 +49,4 @@ public class StopCommand extends GeyserCommand {
return super.builder(manager)
.handler(context -> geyser.getBootstrap().onDisable());
}
@Override
public boolean isSuggestedOpOnly() {
return true;
}
}

View File

@ -105,9 +105,4 @@ public class VersionCommand extends GeyserCommand {
}
}
}
@Override
public boolean isSuggestedOpOnly() {
return true;
}
}

View File

@ -25,19 +25,32 @@
package org.geysermc.geyser.extension.command;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.geyser.api.extension.Extension;
import org.geysermc.geyser.command.GeyserCommand;
public abstract class GeyserExtensionCommand extends GeyserCommand {
private final Extension extension;
private final String rootCommand;
public GeyserExtensionCommand(Extension extension, String name, String description, String permission) {
super(name, description, permission);
public GeyserExtensionCommand(@NonNull Extension extension, @NonNull String name, @Nullable String description, @Nullable String permission, boolean executableOnConsole, boolean bedrockOnly) {
super(name, description, permission, executableOnConsole, bedrockOnly);
this.extension = extension;
this.rootCommand = extension.rootCommand();
if (this.rootCommand == null || this.rootCommand.isBlank()) {
throw new IllegalStateException("rootCommand of extension " + extension.name() + " may not be null or blank");
}
}
public Extension extension() {
public final Extension extension() {
return this.extension;
}
@Override
public final String rootCommand() {
return this.rootCommand;
}
}