Skip to content

Commit

Permalink
feat: remove i18n, add help formatter
Browse files Browse the repository at this point in the history
  • Loading branch information
entrypointkr committed Feb 23, 2023
1 parent 89a6689 commit bf11503
Show file tree
Hide file tree
Showing 24 changed files with 354 additions and 813 deletions.
2 changes: 1 addition & 1 deletion bukkit/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ plugins {
id 'signing'
}

version '0.5.0'
version '0.6.0'

repositories {
mavenCentral()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,38 +1,61 @@
package io.typecraft.command.bukkit;

import io.typecraft.command.Argument;
import io.typecraft.command.bukkit.i18n.BukkitLangId;
import io.vavr.control.Try;
import lombok.experimental.UtilityClass;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
import org.bukkit.potion.PotionEffectType;

import java.util.Arrays;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

@UtilityClass
public class BukkitArgument {
public class BukkitArguments {
public static final Argument<Player> playerArg =
Argument.ofUnary(
BukkitLangId.typeBukkitPlayer,
"player",
s -> Optional.ofNullable(Bukkit.getPlayer(s)),
() -> Bukkit.getOnlinePlayers().stream().map(Player::getName).collect(Collectors.toList())
);
@SuppressWarnings("deprecation")
public static final Argument<OfflinePlayer> offlinePlayerArg =
Argument.ofUnary(
BukkitLangId.typeBukkitOfflinePlayer,
"offlineplayer",
s -> Optional.of(Bukkit.getOfflinePlayer(s)),
() -> Bukkit.getOnlinePlayers().stream().map(Player::getName).collect(Collectors.toList())
);

public static final Argument<Material> materialArg =
Argument.ofUnary(
BukkitLangId.typeMaterial,
"material",
s -> Try.of(() -> Material.valueOf(s)).toJavaOptional(),
() -> Arrays.stream(Material.values()).map(Material::name).collect(Collectors.toList())
);

public static final Argument<PotionEffectType> potionArg =
Argument.ofUnary(
"potion",
s -> Optional.ofNullable(PotionEffectType.getByName(s)),
() -> Arrays.stream(PotionEffectType.values())
.filter(Objects::nonNull)
.map(PotionEffectType::getName)
.collect(Collectors.toList())
);

@SuppressWarnings("deprecation")
public static final Argument<Enchantment> enchantArg =
Argument.ofUnary(
"enchant",
s -> Optional.ofNullable(Enchantment.getByName(s)),
() -> Arrays.stream(Enchantment.values())
.filter(Objects::nonNull)
.map(Enchantment::getName)
.collect(Collectors.toList())
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,9 @@

import io.typecraft.command.Command;
import io.typecraft.command.*;
import io.typecraft.command.bukkit.config.BukkitCommandConfig;
import io.typecraft.command.config.CommandConfig;
import io.typecraft.command.i18n.Language;
import io.typecraft.command.i18n.MessageId;
import io.vavr.control.Either;
import lombok.experimental.UtilityClass;
import org.bukkit.Bukkit;
import org.bukkit.command.*;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
Expand All @@ -19,74 +13,66 @@
import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Supplier;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@UtilityClass
public class BukkitCommand {
public class BukkitCommands {
/**
* Register a command with CommandConfig
* Register a command with simple usage
*
* @param commandName The main name of the command
* @param executor The executor of the command
* @param tabCompleter The tab completer of the command
* @param getConfig The config for internalization
* @param plugin The plugin that depends on the command
* @param command The node of the command
* @param <A> The result of the command
* @param <A> The result of the command
* @param commandName The main name of the command
* @param command The node of the command
* @param executor The executor of the command
* @param plugin The plugin that depends on the command
*/
public static <A> void registerWithConfig(
public static <A> void register(
String commandName,
Command<A> command,
BiConsumer<CommandSender, A> executor,
BiFunction<CommandSender, A, List<String>> tabCompleter,
Supplier<CommandConfig> getConfig,
JavaPlugin plugin,
Command<A> command
JavaPlugin plugin
) {
PluginTabExecutor<A> pluginTabExecutor = new PluginTabExecutor<>(command, commandName, plugin, getConfig, executor, tabCompleter);
PluginCommand pluginCmd = plugin.getCommand(commandName);
if (pluginCmd == null) {
throw new IllegalArgumentException(String.format("Unknown command name: '%s'", commandName));
}
pluginCmd.setExecutor(pluginTabExecutor);
pluginCmd.setTabCompleter(pluginTabExecutor);
registerPrime(commandName, command, executor, (sender, a) -> Collections.emptyList(), CommandConfig.empty, plugin);
}

/**
* To use this register, your plugin must depend on `BukkitCommand` plugin. If you don't, use `BukkitCommand.registerWithConfig` instead.
* Register a command
*
* @param <A> The result of the command
* @param commandName The main name of the command
* @param command The node of the command
* @param executor The executor of the command
* @param tabCompleter The tab completer of the command
* @param config The configuration for the command
* @param plugin The plugin that depends on the command
* @param command The node of the command
* @param <A> The result of the command
*/
public static <A> void register(
String commandName,
public static <A> void registerPrime(
String commandName, Command<A> command,
BiConsumer<CommandSender, A> executor,
BiFunction<CommandSender, A, List<String>> tabCompleter,
JavaPlugin plugin,
Command<A> command
CommandConfig config,
JavaPlugin plugin
) {
registerWithConfig(commandName, executor, tabCompleter, () -> {
Plugin kernel = Bukkit.getPluginManager().getPlugin("BukkitCommand");
return kernel instanceof CommandBukkitPlugin
? ((CommandBukkitPlugin) kernel).getCommandConfig()
: BukkitCommandConfig.ofDefault();
}, plugin, command);
PluginTabExecutor<A> pluginTabExecutor = new PluginTabExecutor<>(config, command, commandName, plugin, executor, tabCompleter);
PluginCommand pluginCmd = plugin.getCommand(commandName);
if (pluginCmd == null) {
throw new IllegalArgumentException(String.format("Unknown command name: '%s'", commandName));
}
pluginCmd.setExecutor(pluginTabExecutor);
pluginCmd.setTabCompleter(pluginTabExecutor);
}


public static <A> Optional<CommandSuccess<A>> execute(Map<String, String> langs, CommandSender sender, String label, String[] args, Command<A> command) {
public static <A> Optional<CommandSuccess<A>> execute(CommandSender sender, String label, String[] args, Command<A> command, CommandConfig config) {
Either<CommandFailure<A>, CommandSuccess<A>> result = Command.parse(args, command);
if (result.isRight()) {
CommandSuccess<A> success = result.get();
return Optional.of(success);
} else if (result.isLeft()) {
CommandFailure<A> failure = result.getLeft();
for (String line : getFailureMessage(langs, label, failure)) {
for (String line : getFailureMessage(config, label, failure)) {
sender.sendMessage(line);
}
}
Expand All @@ -97,7 +83,7 @@ public static <A> CommandTabResult<A> tabComplete(String[] args, Command<A> comm
return Command.tabComplete(args, command);
}

static <A> List<String> getCommandUsages(Map<String, String> langs, String label, String[] args, int position, Command<A> cmd) {
static <A> List<String> getCommandUsages(Function<CommandHelp, String> formatter, String label, String[] args, int position, Command<A> cmd) {
String[] succArgs = args.length >= 1
? Arrays.copyOfRange(args, 0, position)
: new String[0];
Expand All @@ -110,60 +96,47 @@ static <A> List<String> getCommandUsages(Map<String, String> langs, String label
))
.collect(Collectors.toList());
CommandSpec spec = Command.getSpec(pair.getValue());
String argSuffix = spec.getArguments().stream().anyMatch(id -> !id.getId().isEmpty())
? " §e" + spec.getArguments().stream()
.map(s -> String.format("(%s)", s.getMessage(langs)))
.collect(Collectors.joining(" "))
: "";
String description = spec.getDescriptionId().getMessage(langs);
String descSuffix = description.isEmpty()
? ""
: " §f- " + description;
return String.format("§a/%s %s", label, String.join(" ", usageArgs)) + argSuffix + descSuffix;
return formatter.apply(CommandHelp.of(label, usageArgs, spec));
})
.collect(Collectors.toList());
}

private static <A> List<String> getFailureMessage(Map<String, String> langs, String label, CommandFailure<A> failure) {
private static <A> List<String> getFailureMessage(CommandConfig config, String label, CommandFailure<A> failure) {
if (failure instanceof CommandFailure.FewArguments) {
CommandFailure.FewArguments<A> fewArgs = (CommandFailure.FewArguments<A>) failure;
return getCommandUsages(langs, label, fewArgs.getArguments(), fewArgs.getIndex(), fewArgs.getCommand());
return getCommandUsages(config.getFormatter(), label, fewArgs.getArguments(), fewArgs.getIndex(), fewArgs.getCommand());
} else if (failure instanceof CommandFailure.UnknownSubCommand) {
CommandFailure.UnknownSubCommand<A> unknown = (CommandFailure.UnknownSubCommand<A>) failure;
String input = unknown.getArguments()[unknown.getIndex()];
List<String> usages = new ArrayList<>(getCommandUsages(
langs, label, unknown.getArguments(), unknown.getIndex(), unknown.getCommand()
config.getFormatter(), label, unknown.getArguments(), unknown.getIndex(), unknown.getCommand()
));
usages.add(String.format(MessageId.commandNotExists.getMessage(langs), input));
usages.add(String.format("Command '%s' doesn't exists!", input));
return usages;
}
return Collections.singletonList(MessageId.commandWrongUsage.getMessage(langs));
return Collections.singletonList("Wrong command!");
}

private static class PluginTabExecutor<A> implements CommandExecutor, TabCompleter, PluginIdentifiableCommand {
private final CommandConfig config;
private final Command<A> command;
private final String commandName;
private final Plugin plugin;
private final Supplier<CommandConfig> getConfig;
private final BiConsumer<CommandSender, A> executor;
private final BiFunction<CommandSender, A, List<String>> tabCompleter;

public PluginTabExecutor(Command<A> command, String commandName, Plugin plugin, Supplier<CommandConfig> getConfig, BiConsumer<CommandSender, A> executor, BiFunction<CommandSender, A, List<String>> tabCompleter) {
public PluginTabExecutor(CommandConfig config, Command<A> command, String commandName, Plugin plugin, BiConsumer<CommandSender, A> executor, BiFunction<CommandSender, A, List<String>> tabCompleter) {
this.config = config;
this.command = command;
this.commandName = commandName;
this.plugin = plugin;
this.getConfig = getConfig;
this.executor = executor;
this.tabCompleter = tabCompleter;
}

@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull org.bukkit.command.Command cmd, @NotNull String label, @NotNull String[] args) {
CommandConfig config = getConfig.get();
Player player = sender instanceof Player ? ((Player) sender) : null;
Locale locale = player != null ? Language.parseLocaleFrom(player.getLocale()).orElse(null) : config.getDefaultLocale();
Map<String, String> langs = config.getPluginMessagesWithBase(locale, plugin.getName());
execute(langs, sender, label, args, command)
execute(sender, label, args, command, config)
.ifPresent(succ -> executor.accept(sender, succ.getCommand()));
return true;
}
Expand Down

0 comments on commit bf11503

Please sign in to comment.