Skip to content

Commit

Permalink
feature: update to cloud v2
Browse files Browse the repository at this point in the history
This is still a W.I.P. as Cloud v2 is nowhere near ready to be released. There are no up-to-date builds in the OSS repository, so this currently relies on the local Maven repository.
  • Loading branch information
Citymonstret committed Dec 26, 2023
1 parent b6a6878 commit 5b832c5
Show file tree
Hide file tree
Showing 26 changed files with 158 additions and 192 deletions.
2 changes: 2 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ java {

repositories {
mavenCentral()
mavenLocal()
maven { url = uri("https://repo.papermc.io/repository/maven-public/") }
}

Expand Down Expand Up @@ -82,6 +83,7 @@ tasks {
compileJava {
options.compilerArgs.addAll(arrayOf("-Xmaxerrs", "1000"))
options.compilerArgs.add("-Xlint:all")
options.compilerArgs.add("-parameters")
for (disabledLint in arrayOf("processing", "path", "fallthrough", "serial"))
options.compilerArgs.add("-Xlint:$disabledLint")
options.isDeprecation = true
Expand Down
2 changes: 1 addition & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
annotations = "24.1.0"

# Cloud command system
cloud = "1.8.4"
cloud = "2.0.0-SNAPSHOT"

# Gradle plugins
shadow = "8.1.1"
Expand Down
117 changes: 48 additions & 69 deletions src/main/java/com/thevoxelbox/voxelsniper/command/CommandRegistry.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,20 @@
import cloud.commandframework.annotations.Argument;
import cloud.commandframework.annotations.MethodCommandExecutionHandler;
import cloud.commandframework.annotations.injection.ParameterInjectorRegistry;
import cloud.commandframework.arguments.CommandArgument;
import cloud.commandframework.arguments.parser.StandardParameters;
import cloud.commandframework.arguments.standard.EnumArgument;
import cloud.commandframework.arguments.standard.EnumParser;
import cloud.commandframework.bukkit.BukkitCommandManager;
import cloud.commandframework.bukkit.CloudBukkitCapabilities;
import cloud.commandframework.captions.CaptionVariable;
import cloud.commandframework.context.CommandContext;
import cloud.commandframework.exceptions.ArgumentParseException;
import cloud.commandframework.exceptions.CommandExecutionException;
import cloud.commandframework.exceptions.InvalidCommandSenderException;
import cloud.commandframework.exceptions.InvalidSyntaxException;
import cloud.commandframework.exceptions.NoPermissionException;
import cloud.commandframework.exceptions.handling.ExceptionHandler;
import cloud.commandframework.exceptions.parsing.ParserException;
import cloud.commandframework.execution.CommandExecutionCoordinator;
import cloud.commandframework.execution.FilteringCommandSuggestionProcessor;
import cloud.commandframework.keys.CloudKey;
import cloud.commandframework.keys.SimpleCloudKey;
import cloud.commandframework.meta.CommandMeta;
import cloud.commandframework.paper.PaperCommandManager;
import cloud.commandframework.services.types.ConsumerService;
import com.fastasyncworldedit.core.configuration.Caption;
Expand Down Expand Up @@ -59,19 +55,19 @@

public class CommandRegistry {

public static final CloudKey<Snipe> SNIPE_KEY = createTypeKey(
public static final CloudKey<Snipe> SNIPE_KEY = createCloudKey(
"snipe", Snipe.class
);
public static final CloudKey<PerformerSnipe> PERFORMER_SNIPE_KEY = createTypeKey(
public static final CloudKey<PerformerSnipe> PERFORMER_SNIPE_KEY = createCloudKey(
"snipe", PerformerSnipe.class
);
public static final CloudKey<Toolkit> TOOLKIT_KEY = createTypeKey(
public static final CloudKey<Toolkit> TOOLKIT_KEY = createCloudKey(
"toolkit", Toolkit.class
);

private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
private static final String NO_DESCRIPTION = "No Description.";
private static final CommandMeta.Key<Boolean> REQUIRE_TOOLKIT = createMetaKey(
private static final CloudKey<Boolean> REQUIRE_TOOLKIT = createCloudKey(
"require-toolkit",
Boolean.class
);
Expand Down Expand Up @@ -138,18 +134,16 @@ private BukkitCommandManager<SniperCommander> createCommandManager() throws Exce
// Handles post-processor.
commandManager.registerCommandPostProcessor(context -> {
// Ensures that we are working with a voxel sniper annotated command.
CommandContext<SniperCommander> commandContext = context.getCommandContext();
Command<SniperCommander> command = context.getCommand();
if (!(commandContext.getSender() instanceof Sniper sniper)
|| !(command.getCommandExecutionHandler() instanceof MethodCommandExecutionHandler<SniperCommander> handler)) {
CommandContext<SniperCommander> commandContext = context.commandContext();
Command<SniperCommander> command = context.command();
if (!(commandContext.sender() instanceof Sniper sniper)
|| !(command.commandExecutionHandler() instanceof MethodCommandExecutionHandler<SniperCommander> handler)) {
return;
}

Toolkit toolkit;
// Toolkit requirement relies on the custom annotation.
if (command.getCommandMeta()
.get(REQUIRE_TOOLKIT)
.orElse(false)) {
if (command.commandMeta().getOrDefault(REQUIRE_TOOLKIT, false)) {
if ((toolkit = sniper.getCurrentToolkit()) == null) {
sniper.print(Caption.of("voxelsniper.command.missing-toolkit"));
ConsumerService.interrupt();
Expand Down Expand Up @@ -181,54 +175,49 @@ private BukkitCommandManager<SniperCommander> createCommandManager() throws Exce
});

// Handles exceptions.
commandManager.registerExceptionHandler(InvalidSyntaxException.class, (commander, e) ->
commander.print(Caption.of(
commandManager.exceptionController().registerHandler(InvalidSyntaxException.class, ctx ->
ctx.context().sender().print(Caption.of(
"voxelsniper.command.invalid-command-syntax",
e.getCorrectSyntax()
)));
commandManager.registerExceptionHandler(InvalidCommandSenderException.class, (commander, e) ->
commander.print(Caption.of(
ctx.exception().getCorrectSyntax()
))
).registerHandler(InvalidCommandSenderException.class, ctx ->
ctx.context().sender().print(Caption.of(
"voxelsniper.command.invalid-sender-type",
e.getRequiredSender().getSimpleName()
)));
commandManager.registerExceptionHandler(NoPermissionException.class, (commander, e) ->
commander.print(Caption.of(
ctx.exception().getRequiredSender().getSimpleName()
))
).registerHandler(NoPermissionException.class, ctx ->
ctx.context().sender().print(Caption.of(
"voxelsniper.command.missing-permission",
e.getMissingPermission()
)));
commandManager.registerExceptionHandler(ArgumentParseException.class, (commander, e) -> {
Throwable t = e.getCause();

if (t instanceof VoxelCommandElementParseException ve) {
commander.print(ve.getErrorMessage());
} else if (t instanceof EnumArgument.EnumParseException ee) {
commander.print(Caption.of(
ctx.exception().missingPermission()
))
).registerHandler(
ArgumentParseException.class,
ExceptionHandler.unwrappingHandler()
).registerHandler(VoxelCommandElementParseException.class, ctx ->
ctx.context().sender().print(ctx.exception().getErrorMessage())
).registerHandler(EnumParser.EnumParseException.class, ctx ->
ctx.context().sender().print(Caption.of(
"voxelsniper.command.invalid-enum",
ee.getInput(),
ctx.exception().getInput(),
VoxelSniperText.formatList(
Arrays.stream(ee.getEnumClass().getEnumConstants()).toList(),
Arrays.stream(ctx.exception().getEnumClass().getEnumConstants()).toList(),
(value, value2) -> Integer.compare(value.ordinal(), value2.ordinal()),
value -> TextComponent.of(value.name().toLowerCase(Locale.ROOT)),
"voxelsniper.command.invalid-enum"
)
));
} else if (t instanceof ParserException pe) {
commander.print(Caption.of(
pe.errorCaption()
.getKey()
))
).registerHandler(ParserException.class, ctx ->
ctx.context().sender().print(Caption.of(
ctx.exception().errorCaption()
.key()
.replace("argument.parse.failure.", "voxelsniper.command.invalid-"),
Arrays.stream(pe.captionVariables())
.map(CaptionVariable::getValue)
Arrays.stream(ctx.exception().captionVariables())
.map(CaptionVariable::value)
.toArray(Object[]::new)
));
} else {
commander.print(Caption.of("voxelsniper.error.unexpected"));
e.printStackTrace();
}
});
commandManager.registerExceptionHandler(CommandExecutionException.class, (commander, e) -> {
commander.print(Caption.of("voxelsniper.error.unexpected"));
e.printStackTrace();
))
).registerHandler(Throwable.class, ctx -> {
ctx.context().sender().print(Caption.of("voxelsniper.error.unexpected"));
ctx.exception().printStackTrace();
});

return commandManager;
Expand All @@ -238,11 +227,7 @@ private AnnotationParser<SniperCommander> createAnnotationParser(BukkitCommandMa
// Creates the annotation parser.
AnnotationParser<SniperCommander> annotationParser = new AnnotationParser<>(
commandManager,
SniperCommander.class,
parserParameters -> CommandMeta.simple()
.with(CommandMeta.DESCRIPTION, parserParameters
.get(StandardParameters.DESCRIPTION, NO_DESCRIPTION))
.build()
SniperCommander.class
);

// Handles the custom annotations.
Expand Down Expand Up @@ -290,7 +275,7 @@ private void handleDynamicRanges(
MethodCommandExecutionHandler<SniperCommander> handler,
Object instance
) {
SniperCommander commander = commandContext.getSender();
SniperCommander commander = commandContext.sender();
MethodCommandExecutionHandler.CommandMethodContext<SniperCommander> methodContext = handler.context();

// Dynamic range is based on executor instance fields, we must postprocess them manually.
Expand All @@ -310,9 +295,7 @@ private void handleDynamicRanges(
argumentName = this.annotationParser.processString(argumentAnnotation.value());
}

CommandArgument<SniperCommander, Number> argument =
(CommandArgument<SniperCommander, Number>) methodContext.commandArguments().get(argumentName);
double number = commandContext.get(argument).doubleValue();
double number = commandContext.<Number>get(argumentName).doubleValue();

DynamicRange dynamicRangeAnnotation = parameter.getAnnotation(DynamicRange.class);
String min = dynamicRangeAnnotation.min();
Expand Down Expand Up @@ -444,12 +427,8 @@ public AnnotationParser<SniperCommander> getAnnotationParser() {
return annotationParser;
}

private static <T> CloudKey<T> createTypeKey(String id, Class<T> clazz) {
return SimpleCloudKey.of("voxelsniper-" + id, TypeToken.get(clazz));
}

private static <T> CommandMeta.Key<T> createMetaKey(String id, Class<T> clazz) {
return CommandMeta.Key.of(TypeToken.get(clazz), "voxelsniper-" + id);
private static <T> CloudKey<T> createCloudKey(String id, Class<T> clazz) {
return CloudKey.of("voxelsniper-" + id, TypeToken.get(clazz));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.util.function.Function;
import java.util.stream.Collectors;

public class VoxelMethodCommandExecutionHandler<C> extends MethodCommandExecutionHandler<C> {

Expand Down Expand Up @@ -40,7 +41,7 @@ public void execute(@NonNull CommandContext<C> commandContext) {
commandContext,
commandContext.flags(),
super.parameters()
)
).stream().map(ParameterValue::value).collect(Collectors.toList())
);
} catch (final Error e) {
throw e;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.thevoxelbox.voxelsniper.command.argument;

import cloud.commandframework.context.CommandContext;
import cloud.commandframework.context.CommandInput;
import cloud.commandframework.exceptions.parsing.NoInputProvidedException;
import com.fastasyncworldedit.core.configuration.Caption;
import com.thevoxelbox.voxelsniper.VoxelSniperPlugin;
Expand All @@ -11,8 +12,6 @@
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.Queue;
import java.util.stream.Stream;

public abstract class AbstractFileArgument implements VoxelCommandElement {
Expand Down Expand Up @@ -41,29 +40,26 @@ public AbstractFileArgument(VoxelSniperPlugin plugin, Path rootPath, String exte
}
}

protected List<String> suggestFiles(CommandContext<SniperCommander> commandContext, String input) {
protected Stream<String> suggestFiles(CommandContext<SniperCommander> commandContext, String input) {
Path inputPath = rootPath.resolve(input);
try (Stream<Path> files = Files.list(Files.isDirectory(inputPath) ? inputPath : inputPath.getParent())) {
return files.map(path -> path.getFileName().toString())
.flatMap(path -> Stream.of(path, path.replace(extension, "")))
.toList();
.flatMap(path -> Stream.of(path, path.replace(extension, "")));
} catch (IOException e) {
throw new RuntimeException(e);
}
}

protected File parseFile(CommandContext<SniperCommander> commandContext, Queue<String> inputQueue) {
String input = inputQueue.peek();
if (input == null) {
protected File parseFile(CommandContext<SniperCommander> commandContext, CommandInput input) {
if (input.peekString().isEmpty()) {
throw new NoInputProvidedException(AbstractFileArgument.class, commandContext);
}

final String fileName = input.readString();
try {
File file = rootPath.resolve(input.endsWith(extension) ? input : input + extension).toFile();
inputQueue.remove();
return file;
return rootPath.resolve(fileName.endsWith(extension) ? fileName : fileName + extension).toFile();
} catch (Exception e) {
throw new VoxelCommandElementParseException(input, Caption.of(
throw new VoxelCommandElementParseException(fileName, Caption.of(
"voxelsniper.command.invalid-file",
input
));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.thevoxelbox.voxelsniper.command.argument;

import cloud.commandframework.context.CommandContext;
import cloud.commandframework.context.CommandInput;
import cloud.commandframework.exceptions.parsing.NoInputProvidedException;
import com.fastasyncworldedit.core.configuration.Caption;
import com.sk89q.worldedit.extension.input.InputParseException;
Expand All @@ -16,7 +17,6 @@

import java.util.List;
import java.util.Locale;
import java.util.Queue;

public abstract class AbstractPatternArgument<T extends Pattern> implements VoxelCommandElement {

Expand Down Expand Up @@ -44,32 +44,31 @@ protected List<String> suggestPatterns(CommandContext<SniperCommander> commandCo
return factory.getSuggestions(input);
}

protected BrushPattern parsePattern(CommandContext<SniperCommander> commandContext, Queue<String> inputQueue) {
String input = inputQueue.peek();
if (input == null) {
protected BrushPattern parsePattern(CommandContext<SniperCommander> commandContext, CommandInput input) {
if (input.peekString().isEmpty()) {
throw new NoInputProvidedException(AbstractPatternArgument.class, commandContext);
}

SniperCommander commander = commandContext.getSender();
SniperCommander commander = commandContext.sender();
ParserContext parserContext = commander.createParserContext();
String patternString = input.readString();
try {
T pattern = factory.parseFromInput(
input.toLowerCase(Locale.ROOT),
patternString.toLowerCase(Locale.ROOT),
parserContext
);
CommandSender sender = commander.getCommandSender();
if (!sender.hasPermission("voxelsniper.ignorelimitations")
&& config.getLitesniperRestrictedMaterials().contains(getPatternResource(input, pattern))) {
throw new VoxelCommandElementParseException(input, Caption.of(
&& config.getLitesniperRestrictedMaterials().contains(getPatternResource(patternString, pattern))) {
throw new VoxelCommandElementParseException(patternString, Caption.of(
"voxelsniper.command.not-allowed",
input
));
}

inputQueue.remove();
return new BrushPattern(pattern, input);
return new BrushPattern(pattern, patternString);
} catch (InputParseException e) {
throw new VoxelCommandElementParseException(input, Caption.of(
throw new VoxelCommandElementParseException(patternString, Caption.of(
parseExceptionCaptionKey,
input
));
Expand Down
Loading

0 comments on commit 5b832c5

Please sign in to comment.