Skip to content

Commit

Permalink
Cloud 2 (#227)
Browse files Browse the repository at this point in the history
* Cloud 2

* Use cloud-translations

* Use AudienceLocaleExtractor

* Update dependencies

* Update cloud

* Update cloud

* merge service files
  • Loading branch information
jpenilla authored Mar 15, 2024
1 parent d71171e commit 96ebd22
Show file tree
Hide file tree
Showing 18 changed files with 258 additions and 523 deletions.
21 changes: 14 additions & 7 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ group = "xyz.jpenilla"
version = "1.8.4-SNAPSHOT".decorateVersion()
description = "Customizable trades for Wandering Traders."

val mcVersion = "1.20.2"
val mcVersion = "1.20.4"

repositories {
mavenCentral()
Expand All @@ -37,12 +37,16 @@ dependencies {
compileOnly("io.papermc.paper", "paper-api", "1.20.1-R0.1-SNAPSHOT")

implementation("io.papermc", "paperlib", "1.0.8")
implementation("xyz.jpenilla", "legacy-plugin-base", "0.0.1+106-SNAPSHOT")
implementation("xyz.jpenilla", "legacy-plugin-base", "0.0.1+108-SNAPSHOT")
implementation("org.bstats", "bstats-bukkit", "3.0.2")

implementation(platform("cloud.commandframework:cloud-bom:1.8.4"))
implementation("cloud.commandframework", "cloud-paper")
implementation("cloud.commandframework", "cloud-minecraft-extras")
implementation(platform("org.incendo:cloud-bom:2.0.0-beta.4"))
implementation(platform("org.incendo:cloud-minecraft-bom:2.0.0-beta.5"))
implementation("org.incendo:cloud-paper")
implementation("org.incendo:cloud-minecraft-extras")
implementation(platform("org.incendo:cloud-translations-bom:1.0.0-SNAPSHOT"))
implementation("org.incendo:cloud-translations-bukkit")
implementation("org.incendo:cloud-translations-minecraft-extras")

implementation("org.incendo.interfaces", "interfaces-paper", "1.0.0-SNAPSHOT")

Expand Down Expand Up @@ -90,15 +94,15 @@ tasks {
archiveFileName.set("${project.name}-${project.version}.jar")
sequenceOf(
"org.bstats",
"cloud.commandframework",
"org.incendo",
"xyz.jpenilla.pluginbase",
"net.kyori",
"io.papermc.lib",
"io.leangen.geantyref",
"org.incendo.interfaces",
).forEach {
relocate(it, "xyz.jpenilla.wanderingtrades.lib.$it")
}
mergeServiceFiles()
}
processResources {
val tokens = mapOf(
Expand All @@ -116,6 +120,9 @@ tasks {
}
}
}
compileJava {
options.compilerArgs.add("-Xlint:-classfile,-processing")
}
}

fun lastCommitHash(): String = indraGit.commit()?.name?.substring(0, 7)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
package xyz.jpenilla.wanderingtrades.command;

import cloud.commandframework.paper.PaperCommandManager;
import org.bukkit.command.CommandSender;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.framework.qual.DefaultQualifier;
import org.incendo.cloud.CommandManager;
import xyz.jpenilla.pluginbase.legacy.Chat;
import xyz.jpenilla.wanderingtrades.WanderingTrades;

@DefaultQualifier(NonNull.class)
public abstract class BaseCommand {
protected final WanderingTrades plugin;
protected final Commands commands;
protected final PaperCommandManager<CommandSender> commandManager;
protected final CommandManager<CommandSender> commandManager;
protected final Chat chat;

protected BaseCommand(final WanderingTrades plugin, final Commands commands) {
Expand Down
91 changes: 33 additions & 58 deletions src/main/java/xyz/jpenilla/wanderingtrades/command/Commands.java
Original file line number Diff line number Diff line change
@@ -1,40 +1,38 @@
package xyz.jpenilla.wanderingtrades.command;

import cloud.commandframework.Command;
import cloud.commandframework.arguments.flags.CommandFlag;
import cloud.commandframework.brigadier.CloudBrigadierManager;
import cloud.commandframework.bukkit.BukkitCaptionKeys;
import cloud.commandframework.bukkit.CloudBukkitCapabilities;
import cloud.commandframework.captions.SimpleCaptionRegistry;
import cloud.commandframework.captions.StandardCaptionKeys;
import cloud.commandframework.execution.CommandExecutionCoordinator;
import cloud.commandframework.execution.FilteringCommandSuggestionProcessor;
import cloud.commandframework.execution.preprocessor.CommandPreprocessingContext;
import cloud.commandframework.keys.CloudKey;
import cloud.commandframework.keys.SimpleCloudKey;
import cloud.commandframework.paper.PaperCommandManager;
import io.leangen.geantyref.TypeToken;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.bukkit.command.CommandSender;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.framework.qual.DefaultQualifier;
import org.incendo.cloud.Command;
import org.incendo.cloud.CommandManager;
import org.incendo.cloud.bukkit.CloudBukkitCapabilities;
import org.incendo.cloud.execution.ExecutionCoordinator;
import org.incendo.cloud.execution.preprocessor.CommandPreprocessingContext;
import org.incendo.cloud.key.CloudKey;
import org.incendo.cloud.paper.PaperCommandManager;
import org.incendo.cloud.parser.flag.CommandFlag;
import org.incendo.cloud.translations.LocaleExtractor;
import xyz.jpenilla.wanderingtrades.WanderingTrades;
import xyz.jpenilla.wanderingtrades.command.argument.TradeConfigArgument;
import xyz.jpenilla.wanderingtrades.command.argument.TradeConfigParser;
import xyz.jpenilla.wanderingtrades.command.commands.AboutCommand;
import xyz.jpenilla.wanderingtrades.command.commands.ConfigCommands;
import xyz.jpenilla.wanderingtrades.command.commands.HelpCommand;
import xyz.jpenilla.wanderingtrades.command.commands.ReloadCommand;
import xyz.jpenilla.wanderingtrades.command.commands.SummonCommands;
import xyz.jpenilla.wanderingtrades.command.commands.TradeCommands;
import xyz.jpenilla.wanderingtrades.config.Messages;
import xyz.jpenilla.wanderingtrades.config.TradeConfig;

import static org.incendo.cloud.translations.TranslationBundle.core;
import static org.incendo.cloud.translations.bukkit.BukkitTranslationBundle.bukkit;
import static org.incendo.cloud.translations.minecraft.extras.AudienceLocaleExtractor.audienceLocaleExtractor;
import static org.incendo.cloud.translations.minecraft.extras.MinecraftExtrasTranslationBundle.minecraftExtras;

@DefaultQualifier(NonNull.class)
public final class Commands {
public static final CloudKey<WanderingTrades> PLUGIN = SimpleCloudKey.of("wt:plugin", TypeToken.get(WanderingTrades.class));
public static final CloudKey<WanderingTrades> PLUGIN = CloudKey.of("wt:plugin", TypeToken.get(WanderingTrades.class));

private final WanderingTrades plugin;
private final PaperCommandManager<CommandSender> commandManager;
Expand All @@ -44,17 +42,12 @@ private Commands(final WanderingTrades plugin, final PaperCommandManager<Command
this.plugin = plugin;
this.commandManager = commandManager;

this.commandManager.commandSuggestionProcessor(new FilteringCommandSuggestionProcessor<>(
FilteringCommandSuggestionProcessor.Filter.<CommandSender>contains(true).andTrimBeforeLastSpace()
));
new ExceptionHandler(plugin, commandManager).register();
this.registerMessageFactories();
this.registerCaptions();
if (this.commandManager.hasCapability(CloudBukkitCapabilities.NATIVE_BRIGADIER)) {
this.commandManager.registerBrigadier();
final @Nullable CloudBrigadierManager<CommandSender, ?> brigManager = this.commandManager.brigadierManager();
if (brigManager != null) {
brigManager.setNativeNumberSuggestions(false);
}
} else if (this.commandManager.hasCapability(CloudBukkitCapabilities.ASYNCHRONOUS_COMPLETION)) {
this.commandManager.registerAsynchronousCompletions();
}
this.registerParsers();
this.commandManager.registerCommandPreProcessor(this::preProcessContext);
Expand All @@ -73,37 +66,24 @@ private void registerCommands() {
commands.forEach(BaseCommand::register);
}

public PaperCommandManager<CommandSender> commandManager() {
public CommandManager<CommandSender> commandManager() {
return this.commandManager;
}

private void registerMessageFactories() {
if (!(this.commandManager.captionRegistry() instanceof final SimpleCaptionRegistry<CommandSender> registry)) {
return;
}
registry.registerMessageFactory(
StandardCaptionKeys.ARGUMENT_PARSE_FAILURE_ENUM,
(caption, sender) -> Messages.COMMAND_ARGUMENT_PARSE_FAILURE_ENUM.message()
);
registry.registerMessageFactory(
BukkitCaptionKeys.ARGUMENT_PARSE_FAILURE_LOCATION_MIXED_LOCAL_ABSOLUTE,
(caption, sender) -> Messages.COMMAND_ARGUMENT_PARSE_FAILURE_LOCATION_MIXED_LOCAL_ABSOLUTE.message()
);
registry.registerMessageFactory(
BukkitCaptionKeys.ARGUMENT_PARSE_FAILURE_LOCATION_INVALID_FORMAT,
(caption, sender) -> Messages.COMMAND_ARGUMENT_PARSE_FAILURE_LOCATION_INVALID_FORMAT.message()
);
private void registerCaptions() {
final LocaleExtractor<CommandSender> extractor = audienceLocaleExtractor(this.plugin.audiences()::sender);
this.commandManager.captionRegistry()
.registerProvider(minecraftExtras(extractor))
.registerProvider(bukkit(extractor))
.registerProvider(core(extractor));
}

private void registerParsers() {
this.commandManager.parserRegistry().registerParserSupplier(
TypeToken.get(TradeConfig.class),
parameters -> new TradeConfigArgument.Parser()
);
this.commandManager.parserRegistry().registerParser(TradeConfigParser.tradeConfigParser());
}

private void preProcessContext(final CommandPreprocessingContext<CommandSender> context) {
context.getCommandContext().store(PLUGIN, this.plugin);
context.commandContext().store(PLUGIN, this.plugin);
}

public CommandFlag.Builder<?> getFlag(final String name) {
Expand All @@ -114,20 +94,15 @@ public void registerFlag(final String name, final CommandFlag.Builder<?> flagBui
this.flagRegistry.put(name, flagBuilder);
}

public void register(final List<Command<CommandSender>> commands) {
public void register(final List<Command<? extends CommandSender>> commands) {
commands.forEach(this.commandManager::command);
}

public static void setup(final WanderingTrades plugin) {
final PaperCommandManager<CommandSender> manager;
try {
manager = PaperCommandManager.createNative(
plugin,
CommandExecutionCoordinator.simpleCoordinator()
);
} catch (final Exception ex) {
throw new RuntimeException("Failed to initialize command manager", ex);
}
final PaperCommandManager<CommandSender> manager = PaperCommandManager.createNative(
plugin,
ExecutionCoordinator.simpleCoordinator()
);
new Commands(plugin, manager);
}
}
Original file line number Diff line number Diff line change
@@ -1,98 +1,51 @@
package xyz.jpenilla.wanderingtrades.command;

import cloud.commandframework.CommandManager;
import cloud.commandframework.exceptions.ArgumentParseException;
import cloud.commandframework.exceptions.InvalidCommandSenderException;
import cloud.commandframework.exceptions.InvalidSyntaxException;
import cloud.commandframework.exceptions.NoPermissionException;
import cloud.commandframework.minecraft.extras.MinecraftExceptionHandler;
import java.util.Objects;
import java.util.regex.Pattern;
import java.util.logging.Level;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.ComponentLike;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.util.ComponentMessageThrowable;
import org.bukkit.command.CommandSender;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.framework.qual.DefaultQualifier;
import org.incendo.cloud.CommandManager;
import org.incendo.cloud.exception.ArgumentParseException;
import org.incendo.cloud.exception.CommandExecutionException;
import org.incendo.cloud.exception.InvalidCommandSenderException;
import org.incendo.cloud.exception.InvalidSyntaxException;
import org.incendo.cloud.exception.NoPermissionException;
import org.incendo.cloud.minecraft.extras.MinecraftExceptionHandler;
import xyz.jpenilla.wanderingtrades.WanderingTrades;
import xyz.jpenilla.wanderingtrades.config.Messages;
import xyz.jpenilla.wanderingtrades.util.Components;
import xyz.jpenilla.wanderingtrades.util.Constants;

import static org.incendo.cloud.exception.handling.ExceptionHandler.unwrappingHandler;

@DefaultQualifier(NonNull.class)
final class ExceptionHandler {
private static final Pattern SYNTAX_HIGHLIGHT_PATTERN = Pattern.compile("[^\\s\\w\\-]");

private final WanderingTrades plugin;
private final CommandManager<CommandSender> commandManager;

ExceptionHandler(final WanderingTrades plugin, final CommandManager<CommandSender> commandManager) {
ExceptionHandler(
final WanderingTrades plugin,
final CommandManager<CommandSender> commandManager
) {
this.plugin = plugin;
this.commandManager = commandManager;
}

void register() {
new MinecraftExceptionHandler<CommandSender>()
.withHandler(MinecraftExceptionHandler.ExceptionType.NO_PERMISSION, ExceptionHandler::noPermission)
.withHandler(MinecraftExceptionHandler.ExceptionType.INVALID_SYNTAX, this::invalidSyntax)
.withHandler(MinecraftExceptionHandler.ExceptionType.INVALID_SENDER, this::invalidSender)
.withHandler(MinecraftExceptionHandler.ExceptionType.ARGUMENT_PARSING, this::argumentParsing)
.withHandler(MinecraftExceptionHandler.ExceptionType.COMMAND_EXECUTION, this::commandExecution)
.withDecorator(ExceptionHandler::decorate)
.apply(this.commandManager, this.plugin.audiences()::sender);
}

private Component commandExecution(final CommandSender commandSender, final Exception ex) {
final Throwable cause = ex.getCause();

if (cause instanceof NoPermissionException noPermissionException) {
return noPermission(noPermissionException);
} else if (cause instanceof InvalidSyntaxException invalidSyntaxException) {
return this.invalidSyntax(invalidSyntaxException);
} else if (cause instanceof InvalidCommandSenderException invalidCommandSenderException) {
return this.invalidSender(invalidCommandSenderException);
} else if (cause instanceof ArgumentParseException argumentParseException) {
return this.argumentParsing(argumentParseException);
}

return MinecraftExceptionHandler.DEFAULT_COMMAND_EXECUTION_FUNCTION.apply(ex);
}

private Component invalidSyntax(final Exception ex) {
final InvalidSyntaxException exception = (InvalidSyntaxException) ex;
final Component correctSyntaxMessage = Component.text(
String.format("/%s", exception.getCorrectSyntax()),
NamedTextColor.GRAY
).replaceText(config -> {
config.match(SYNTAX_HIGHLIGHT_PATTERN);
config.replacement(builder -> builder.color(NamedTextColor.WHITE));
});
return Messages.COMMAND_INVALID_SYNTAX.withPlaceholders(
Components.placeholder("syntax", correctSyntaxMessage)
);
}

private Component invalidSender(final Exception ex) {
final InvalidCommandSenderException exception = (InvalidCommandSenderException) ex;
return Messages.COMMAND_INVALID_SENDER.withPlaceholders(
Components.placeholder("type", exception.getRequiredSender().getSimpleName())
);
}

private Component argumentParsing(final Exception ex) {
final Component causeMessage = Objects.requireNonNull(ComponentMessageThrowable.getOrConvertMessage(ex.getCause()))
.colorIfAbsent(NamedTextColor.GRAY);
return Messages.COMMAND_INVALID_ARGUMENT.withPlaceholders(
Components.placeholder("error", causeMessage)
);
}

private static Component noPermission(final Exception e) {
return Component.translatable("commands.help.failed", NamedTextColor.RED);
}

private static Component decorate(final ComponentLike component) {
return Component.textOfChildren(Constants.PREFIX_COMPONENT, component);
MinecraftExceptionHandler.create(this.plugin.audiences()::sender)
.handler(NoPermissionException.class, (formatter, ctx) -> Component.translatable("commands.help.failed", NamedTextColor.RED))
.defaultInvalidSyntaxHandler()
.defaultInvalidSenderHandler()
.defaultArgumentParsingHandler()
.defaultCommandExecutionHandler(ctx -> this.plugin.getLogger().log(Level.WARNING, "Unexpected exception during command execution", ctx.exception().getCause()))
.decorator(msg -> Component.textOfChildren(Constants.PREFIX_COMPONENT, msg))
.registerTo(this.commandManager);

this.commandManager.exceptionController()
.registerHandler(CommandExecutionException.class, unwrappingHandler(NoPermissionException.class))
.registerHandler(CommandExecutionException.class, unwrappingHandler(InvalidSyntaxException.class))
.registerHandler(CommandExecutionException.class, unwrappingHandler(InvalidCommandSenderException.class))
.registerHandler(CommandExecutionException.class, unwrappingHandler(ArgumentParseException.class));
}
}
Loading

0 comments on commit 96ebd22

Please sign in to comment.