getRootCommand() {
+ return rootCommand;
+ }
+
@Nullable
public NightPluginCommand getCommand(@NotNull String alias) {
return this.getCommands().stream()
@@ -66,6 +95,13 @@ public NightPluginCommand getCommand(@NotNull String alias) {
.findFirst().orElse(null);
}
+ @Nullable
+ public ServerCommand getServerCommand(@NotNull String alias) {
+ return this.serverCommands.stream()
+ .filter(command -> command.getNode().getName().equalsIgnoreCase(alias) || Lists.contains(command.getNode().getAliases(), alias))
+ .findFirst().orElse(null);
+ }
+
public void registerCommand(@NotNull NightPluginCommand command) {
if (this.commands.add(command)) {
CommandUtil.register(this.plugin, command);
@@ -86,4 +122,24 @@ public boolean unregisterCommand(@NotNull NightPluginCommand command) {
}
return false;
}
+
+ public void registerCommand(@NotNull ServerCommand command) {
+ if (!this.serverCommands.contains(command)) {
+ if (command.register()) {
+ this.serverCommands.add(command);
+ }
+ }
+ }
+
+ public boolean unregisterServerCommand(@NotNull String alias) {
+ ServerCommand command = this.getServerCommand(alias);
+ if (command != null) {
+ return this.unregisterCommand(command);
+ }
+ return false;
+ }
+
+ public boolean unregisterCommand(@NotNull ServerCommand command) {
+ return this.serverCommands.remove(command) && command.unregister();
+ }
}
diff --git a/src/main/java/su/nightexpress/nightcore/command/experimental/CommandContext.java b/src/main/java/su/nightexpress/nightcore/command/experimental/CommandContext.java
new file mode 100644
index 0000000..f8f7530
--- /dev/null
+++ b/src/main/java/su/nightexpress/nightcore/command/experimental/CommandContext.java
@@ -0,0 +1,113 @@
+package su.nightexpress.nightcore.command.experimental;
+
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+import org.bukkit.permissions.Permission;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import su.nightexpress.nightcore.NightCorePlugin;
+import su.nightexpress.nightcore.core.CoreLang;
+import su.nightexpress.nightcore.language.message.LangMessage;
+
+public class CommandContext {
+
+ private final NightCorePlugin plugin;
+ private final CommandSender sender;
+ private final Player executor;
+ private final String label;
+ private final String[] args;
+
+ private int argumentIndex;
+
+ public CommandContext(@NotNull NightCorePlugin plugin, @NotNull CommandSender sender, @NotNull String label, String[] args) {
+ this.plugin = plugin;
+ this.sender = sender;
+ this.executor = sender instanceof Player player ? player : null;
+ this.label = label;
+ this.args = args;
+ this.argumentIndex = 0;
+ }
+
+ public void send(@NotNull String string) {
+ this.sender.sendMessage(string);
+ }
+
+ public boolean sendSuccess(@NotNull String string) {
+ this.send(string);
+ return true;
+ }
+
+ public boolean sendFailure(@NotNull String string) {
+ this.send(string);
+ return false;
+ }
+
+ public void send(@NotNull LangMessage message) {
+ message.send(this.sender);
+ }
+
+ public boolean sendSuccess(@NotNull LangMessage message) {
+ this.send(message);
+ return true;
+ }
+
+ public boolean sendFailure(@NotNull LangMessage message) {
+ this.send(message);
+ return false;
+ }
+
+ public boolean checkPermission(@NotNull Permission permission) {
+ return this.sender.hasPermission(permission);
+ }
+
+ public boolean checkPermission(@NotNull String permission) {
+ return this.sender.hasPermission(permission);
+ }
+
+ public boolean isPlayer() {
+ return this.executor != null;
+ }
+
+ public int getArgumentIndex() {
+ return argumentIndex;
+ }
+
+ public void setArgumentIndex(int argumentIndex) {
+ this.argumentIndex = argumentIndex;
+ }
+
+ @NotNull
+ public CommandSender getSender() {
+ return sender;
+ }
+
+ @Nullable
+ public Player getExecutor() {
+ return executor;
+ }
+
+ public int length() {
+ return this.args.length;
+ }
+
+ @NotNull
+ public String getLabel() {
+ return label;
+ }
+
+ public String[] getArgs() {
+ return args;
+ }
+
+ public void errorPermission() {
+ this.send(CoreLang.ERROR_NO_PERMISSION.getMessage(plugin));
+ }
+
+ public void errorBadPlayer() {
+ this.send(CoreLang.ERROR_INVALID_PLAYER.getMessage(plugin));
+ }
+
+ public void errorPlayerOnly() {
+ this.send(CoreLang.ERROR_COMMAND_PLAYER_ONLY.getMessage(plugin));
+ }
+}
diff --git a/src/main/java/su/nightexpress/nightcore/command/experimental/ImprovedCommands.java b/src/main/java/su/nightexpress/nightcore/command/experimental/ImprovedCommands.java
new file mode 100644
index 0000000..f8eb047
--- /dev/null
+++ b/src/main/java/su/nightexpress/nightcore/command/experimental/ImprovedCommands.java
@@ -0,0 +1,18 @@
+package su.nightexpress.nightcore.command.experimental;
+
+import org.jetbrains.annotations.NotNull;
+import su.nightexpress.nightcore.NightCorePlugin;
+import su.nightexpress.nightcore.command.experimental.node.ChainedNode;
+
+public interface ImprovedCommands extends NightCorePlugin {
+
+ @NotNull
+ default ServerCommand getRootCommand() {
+ return this.getCommandManager().getRootCommand();
+ }
+
+ @NotNull
+ default ChainedNode getRootNode() {
+ return this.getCommandManager().getRootCommand().getNode();
+ }
+}
diff --git a/src/main/java/su/nightexpress/nightcore/command/experimental/RootCommand.java b/src/main/java/su/nightexpress/nightcore/command/experimental/RootCommand.java
new file mode 100644
index 0000000..7661a12
--- /dev/null
+++ b/src/main/java/su/nightexpress/nightcore/command/experimental/RootCommand.java
@@ -0,0 +1,112 @@
+package su.nightexpress.nightcore.command.experimental;
+
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandSender;
+import org.jetbrains.annotations.NotNull;
+import su.nightexpress.nightcore.NightCorePlugin;
+import su.nightexpress.nightcore.command.experimental.builder.ChainedNodeBuilder;
+import su.nightexpress.nightcore.command.experimental.builder.DirectNodeBuilder;
+import su.nightexpress.nightcore.command.experimental.builder.NodeBuilder;
+import su.nightexpress.nightcore.command.experimental.node.ChainedNode;
+import su.nightexpress.nightcore.command.experimental.node.CommandNode;
+import su.nightexpress.nightcore.command.experimental.node.DirectNode;
+import su.nightexpress.nightcore.command.impl.WrappedCommand;
+import su.nightexpress.nightcore.util.CommandUtil;
+import su.nightexpress.nightcore.util.Lists;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.function.Consumer;
+
+public class RootCommand implements ServerCommand {
+
+ private final P plugin;
+ private final S node;
+
+ private WrappedCommand backend;
+
+ public RootCommand(@NotNull P plugin, @NotNull S node) {
+ this.plugin = plugin;
+ this.node = node;
+ }
+
+ @NotNull
+ public static RootCommand direct(@NotNull T plugin, @NotNull String name, @NotNull Consumer consumer) {
+ return direct(plugin, new String[] {name}, consumer);
+ }
+
+ @NotNull
+ public static RootCommand chained(@NotNull T plugin, @NotNull String name, @NotNull Consumer consumer) {
+ return chained(plugin, new String[] {name}, consumer);
+ }
+
+ @NotNull
+ public static RootCommand direct(@NotNull T plugin, @NotNull String[] aliases, @NotNull Consumer consumer) {
+ DirectNodeBuilder builder = DirectNode.builder(plugin, aliases);
+ consumer.accept(builder);
+ return build(plugin, builder);
+ }
+
+ @NotNull
+ public static RootCommand chained(@NotNull T plugin, @NotNull String[] aliases, @NotNull Consumer consumer) {
+ ChainedNodeBuilder builder = ChainedNode.builder(plugin, aliases);
+ consumer.accept(builder);
+ return build(plugin, builder);
+ }
+
+ @NotNull
+ public static > RootCommand build(@NotNull T plugin, @NotNull B builder) {
+ return new RootCommand<>(plugin, builder.build());
+ }
+
+ @Override
+ public boolean register() {
+ this.backend = new WrappedCommand(this.plugin, this, this,
+ this.node.getName(),
+ this.node.getAliases(),
+ this.node.getDescription(),
+ this.node.getUsage()
+ );
+ return CommandUtil.register(this.plugin, this.backend);
+ }
+
+ @Override
+ public boolean unregister() {
+ if (CommandUtil.unregister(this.getNode().getName())) {
+ this.backend = null;
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public List onTabComplete(@NotNull CommandSender sender, @NotNull Command cmd, @NotNull String label, String[] args) {
+ if (args.length == 0) return Collections.emptyList();
+
+ //int index = 0;//args.length - 1;
+ //String input = args[index];
+ TabContext context = new TabContext(sender, label, args, 0);
+ List samples = this.node.getTab(context);
+
+ return Lists.getSequentialMatches(samples, context.getInput());
+ }
+
+ @Override
+ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
+ CommandContext commandContext = new CommandContext(this.plugin, sender, label, args);
+
+ return this.node.run(commandContext);
+ }
+
+ @Override
+ @NotNull
+ public S getNode() {
+ return node;
+ }
+
+ @Override
+ @NotNull
+ public WrappedCommand getBackend() {
+ return backend;
+ }
+}
diff --git a/src/main/java/su/nightexpress/nightcore/command/experimental/ServerCommand.java b/src/main/java/su/nightexpress/nightcore/command/experimental/ServerCommand.java
new file mode 100644
index 0000000..e290f5f
--- /dev/null
+++ b/src/main/java/su/nightexpress/nightcore/command/experimental/ServerCommand.java
@@ -0,0 +1,17 @@
+package su.nightexpress.nightcore.command.experimental;
+
+import org.bukkit.command.TabExecutor;
+import org.jetbrains.annotations.NotNull;
+import su.nightexpress.nightcore.command.experimental.node.CommandNode;
+import su.nightexpress.nightcore.command.impl.WrappedCommand;
+
+public interface ServerCommand extends TabExecutor {
+
+ boolean register();
+
+ boolean unregister();
+
+ @NotNull CommandNode getNode();
+
+ @NotNull WrappedCommand getBackend();
+}
diff --git a/src/main/java/su/nightexpress/nightcore/command/experimental/TabContext.java b/src/main/java/su/nightexpress/nightcore/command/experimental/TabContext.java
new file mode 100644
index 0000000..b72417f
--- /dev/null
+++ b/src/main/java/su/nightexpress/nightcore/command/experimental/TabContext.java
@@ -0,0 +1,60 @@
+package su.nightexpress.nightcore.command.experimental;
+
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public class TabContext {
+
+ private final CommandSender sender;
+ private final Player player;
+ private final String label;
+ private final String[] args;
+
+ private int index;
+
+ public TabContext(@NotNull CommandSender sender, @NotNull String label, String[] args, int index) {
+ this.sender = sender;
+ this.player = sender instanceof Player user ? user : null;
+ this.label = label;
+ this.args = args;
+ this.index = index;
+ }
+
+ @NotNull
+ public CommandSender getSender() {
+ return sender;
+ }
+
+ @Nullable
+ public Player getPlayer() {
+ return player;
+ }
+
+ @NotNull
+ public String getLabel() {
+ return label;
+ }
+
+ @NotNull
+ public String[] getArgs() {
+ return args;
+ }
+
+ public int getIndex() {
+ return index;
+ }
+
+ public void setIndex(int index) {
+ this.index = index;
+ }
+
+ public String getAtIndex() {
+ return this.args[this.index];
+ }
+
+ public String getInput() {
+ return this.args[this.args.length - 1];
+ }
+}
diff --git a/src/main/java/su/nightexpress/nightcore/command/experimental/argument/ArgumentTypes.java b/src/main/java/su/nightexpress/nightcore/command/experimental/argument/ArgumentTypes.java
new file mode 100644
index 0000000..7a949f8
--- /dev/null
+++ b/src/main/java/su/nightexpress/nightcore/command/experimental/argument/ArgumentTypes.java
@@ -0,0 +1,143 @@
+package su.nightexpress.nightcore.command.experimental.argument;
+
+import org.bukkit.Bukkit;
+import org.bukkit.Material;
+import org.bukkit.World;
+import org.bukkit.enchantments.Enchantment;
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
+import su.nightexpress.nightcore.command.experimental.builder.ArgumentBuilder;
+import su.nightexpress.nightcore.core.CoreLang;
+import su.nightexpress.nightcore.util.BukkitThing;
+import su.nightexpress.nightcore.util.Lists;
+import su.nightexpress.nightcore.util.NumberUtil;
+import su.nightexpress.nightcore.util.Players;
+
+import java.util.function.Function;
+
+public class ArgumentTypes {
+
+ public static final Function STRING = string -> string;
+ public static final Function BOOLEAN = Boolean::parseBoolean;
+ public static final Function INTEGER = string -> NumberUtil.parseInteger(string).orElse(null);
+ public static final Function INTEGER_ABS = string -> NumberUtil.parseInteger(string).map(Math::abs).orElse(null);
+ public static final Function DOUBLE = string -> NumberUtil.parseDouble(string).orElse(null);
+ public static final Function DOUBLE_ABS = string -> NumberUtil.parseDouble(string).map(Math::abs).orElse(null);
+ public static final Function PLAYER = Players::getPlayer;
+ public static final Function WORLD = Bukkit::getWorld;
+ public static final Function MATERIAL = BukkitThing::getMaterial;
+ public static final Function ITEM_MATERIAL = string -> {
+ Material material = BukkitThing.getMaterial(string);
+ return material == null || !material.isItem() ? null : material;
+ };
+ public static final Function BLOCK_MATERIAL = string -> {
+ Material material = BukkitThing.getMaterial(string);
+ return material == null || !material.isBlock() ? null : material;
+ };
+ public static final Function ENCHANTMENT = BukkitThing::getEnchantment;
+ //public static final Function POTION_EFFECT = BukkitThing::getPotionEffect;
+ //public static final Function ATTRIBUTE = BukkitThing::getAttribute;
+
+ @NotNull
+ public static ArgumentBuilder string(@NotNull String name) {
+ return CommandArgument.builder(name, STRING).localized(CoreLang.COMMAND_ARGUMENT_NAME_GENERIC);
+ }
+
+ @NotNull
+ public static ArgumentBuilder bool(@NotNull String name) {
+ return CommandArgument.builder(name, BOOLEAN).localized(CoreLang.COMMAND_ARGUMENT_NAME_GENERIC);
+ }
+
+ @NotNull
+ public static ArgumentBuilder integer(@NotNull String name) {
+ return CommandArgument.builder(name, INTEGER)
+ .localized(CoreLang.COMMAND_ARGUMENT_NAME_GENERIC)
+ .customFailure(CoreLang.ERROR_COMMAND_INVALID_NUMBER_ARGUMENT);
+ }
+
+ @NotNull
+ public static ArgumentBuilder integerAbs(@NotNull String name) {
+ return CommandArgument.builder(name, INTEGER_ABS)
+ .localized(CoreLang.COMMAND_ARGUMENT_NAME_GENERIC)
+ .customFailure(CoreLang.ERROR_COMMAND_INVALID_NUMBER_ARGUMENT);
+ }
+
+ @NotNull
+ public static ArgumentBuilder decimal(@NotNull String name) {
+ return CommandArgument.builder(name, DOUBLE)
+ .localized(CoreLang.COMMAND_ARGUMENT_NAME_GENERIC)
+ .customFailure(CoreLang.ERROR_COMMAND_INVALID_NUMBER_ARGUMENT);
+ }
+
+ @NotNull
+ public static ArgumentBuilder decimalAbs(@NotNull String name) {
+ return CommandArgument.builder(name, DOUBLE_ABS)
+ .localized(CoreLang.COMMAND_ARGUMENT_NAME_GENERIC)
+ .customFailure(CoreLang.ERROR_COMMAND_INVALID_NUMBER_ARGUMENT);
+ }
+
+ @NotNull
+ public static ArgumentBuilder player(@NotNull String name) {
+ return CommandArgument.builder(name, PLAYER)
+ .localized(CoreLang.COMMAND_ARGUMENT_NAME_PLAYER)
+ .customFailure(CoreLang.ERROR_COMMAND_INVALID_PLAYER_ARGUMENT)
+ .withSamples(tabContext -> Players.playerNames(tabContext.getPlayer()));
+ }
+
+ @NotNull
+ public static ArgumentBuilder playerName(@NotNull String name) {
+ return CommandArgument.builder(name, STRING)
+ .localized(CoreLang.COMMAND_ARGUMENT_NAME_PLAYER)
+ .withSamples(tabContext -> Players.playerNames(tabContext.getPlayer()));
+ }
+
+ @NotNull
+ public static ArgumentBuilder world(@NotNull String name) {
+ return CommandArgument.builder(name, WORLD)
+ .localized(CoreLang.COMMAND_ARGUMENT_NAME_WORLD)
+ .customFailure(CoreLang.ERROR_COMMAND_INVALID_WORLD_ARGUMENT)
+ .withSamples(tabContext -> Lists.worldNames());
+ }
+
+ @NotNull
+ public static ArgumentBuilder material(@NotNull String name) {
+ return CommandArgument.builder(name, MATERIAL)
+ .localized(CoreLang.COMMAND_ARGUMENT_NAME_MATERIAL)
+ .customFailure(CoreLang.ERROR_COMMAND_INVALID_MATERIAL_ARGUMENT);
+ }
+
+ @NotNull
+ public static ArgumentBuilder itemMaterial(@NotNull String name) {
+ return CommandArgument.builder(name, ITEM_MATERIAL)
+ .localized(CoreLang.COMMAND_ARGUMENT_NAME_ITEM_MATERIAL)
+ .customFailure(CoreLang.ERROR_COMMAND_INVALID_MATERIAL_ARGUMENT);
+ }
+
+ @NotNull
+ public static ArgumentBuilder blockMaterial(@NotNull String name) {
+ return CommandArgument.builder(name, BLOCK_MATERIAL)
+ .localized(CoreLang.COMMAND_ARGUMENT_NAME_BLOCK_MATERIAL)
+ .customFailure(CoreLang.ERROR_COMMAND_INVALID_MATERIAL_ARGUMENT);
+ }
+
+ @NotNull
+ public static ArgumentBuilder enchantment(@NotNull String name) {
+ return CommandArgument.builder(name, ENCHANTMENT)
+ .localized(CoreLang.COMMAND_ARGUMENT_NAME_ENCHANTMENT)
+ .customFailure(CoreLang.ERROR_COMMAND_INVALID_ENCHANTMENT_ARGUMENT);
+ }
+
+ /*@NotNull
+ public static ArgumentBuilder potionEffect(@NotNull String name) {
+ return CommandArgument.builder(name, POTION_EFFECT)
+ .localized(CoreLang.COMMAND_ARGUMENT_NAME_POTION_EFFECT)
+ .customFailure(CoreLang.ERROR_INVALID_POTION_EFFECT);
+ }
+
+ @NotNull
+ public static ArgumentBuilder attribute(@NotNull String name) {
+ return CommandArgument.builder(name, ATTRIBUTE)
+ .localized(CoreLang.COMMAND_ARGUMENT_NAME_ATTRIBUTE)
+ .customFailure(CoreLang.ERROR_INVALID_ATTRIBUTE);
+ }*/
+}
diff --git a/src/main/java/su/nightexpress/nightcore/command/experimental/argument/CommandArgument.java b/src/main/java/su/nightexpress/nightcore/command/experimental/argument/CommandArgument.java
new file mode 100644
index 0000000..c3c5fa1
--- /dev/null
+++ b/src/main/java/su/nightexpress/nightcore/command/experimental/argument/CommandArgument.java
@@ -0,0 +1,106 @@
+package su.nightexpress.nightcore.command.experimental.argument;
+
+import org.bukkit.command.CommandSender;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import su.nightexpress.nightcore.command.experimental.TabContext;
+import su.nightexpress.nightcore.command.experimental.builder.ArgumentBuilder;
+import su.nightexpress.nightcore.core.CoreLang;
+import su.nightexpress.nightcore.language.message.LangMessage;
+import su.nightexpress.nightcore.util.Placeholders;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.function.Function;
+
+public class CommandArgument {
+
+ private final String name;
+ private final Function parser;
+ private final boolean required;
+ private final String localized;
+ private final String permission;
+ private final Function> samples;
+ private final LangMessage failureMessage;
+
+ public CommandArgument(@NotNull String name,
+ @NotNull Function parser,
+ boolean required,
+ @Nullable String localized,
+ @Nullable String permission,
+ @Nullable LangMessage failureMessage,
+ @Nullable Function> samples) {
+ this.name = name.toLowerCase();
+ this.parser = parser;
+ this.required = required;
+ this.samples = samples;
+ this.localized = this.getLocalized(localized);
+ this.permission = permission;
+ this.failureMessage = failureMessage;
+ }
+
+ @NotNull
+ public static ArgumentBuilder builder(@NotNull String name, @NotNull Function parser) {
+ return new ArgumentBuilder<>(name, parser);
+ }
+
+ @Nullable
+ public ParsedArgument parse(@NotNull String str) {
+ T result = this.parser.apply(str);
+ return result == null ? null : new ParsedArgument<>(result);
+ }
+
+ public boolean hasPermission(@NotNull CommandSender sender) {
+ return this.permission == null || sender.hasPermission(this.permission);
+ }
+
+ @NotNull
+ public List getSamples(@NotNull TabContext context) {
+ return this.samples == null ? Collections.emptyList() : this.samples.apply(context);
+ }
+
+ @NotNull
+ private String getLocalized(@Nullable String localized) {
+ if (localized == null) {
+ localized = this.name;
+ }
+
+ String format = (this.isRequired() ? CoreLang.COMMAND_ARGUMENT_FORMAT_REQUIRED : CoreLang.COMMAND_ARGUMENT_FORMAT_OPTIONAL).getString();
+
+ return format.replace(Placeholders.GENERIC_NAME, localized);
+ }
+
+ @NotNull
+ public LangMessage getFailureMessage() {
+ return this.failureMessage == null ? CoreLang.ERROR_COMMAND_PARSE_ARGUMENT.getMessage() : this.failureMessage;
+ }
+
+ @NotNull
+ public String getName() {
+ return name;
+ }
+
+ @NotNull
+ public Function getParser() {
+ return parser;
+ }
+
+ public boolean isRequired() {
+ return required;
+ }
+
+ @NotNull
+ public String getLocalized() {
+ return this.localized == null ? this.name : this.localized;
+ }
+
+ @Nullable
+ public String getPermission() {
+ return permission;
+ }
+
+ @NotNull
+ public Function> getSamples() {
+ return samples;
+ }
+}
diff --git a/src/main/java/su/nightexpress/nightcore/command/experimental/argument/ParsedArgument.java b/src/main/java/su/nightexpress/nightcore/command/experimental/argument/ParsedArgument.java
new file mode 100644
index 0000000..b970652
--- /dev/null
+++ b/src/main/java/su/nightexpress/nightcore/command/experimental/argument/ParsedArgument.java
@@ -0,0 +1,14 @@
+package su.nightexpress.nightcore.command.experimental.argument;
+
+public class ParsedArgument {
+
+ private final T result;
+
+ public ParsedArgument(T result) {
+ this.result = result;
+ }
+
+ public T getResult() {
+ return result;
+ }
+}
diff --git a/src/main/java/su/nightexpress/nightcore/command/experimental/argument/ParsedArguments.java b/src/main/java/su/nightexpress/nightcore/command/experimental/argument/ParsedArguments.java
new file mode 100644
index 0000000..5c7264f
--- /dev/null
+++ b/src/main/java/su/nightexpress/nightcore/command/experimental/argument/ParsedArguments.java
@@ -0,0 +1,184 @@
+package su.nightexpress.nightcore.command.experimental.argument;
+
+import org.bukkit.Material;
+import org.bukkit.World;
+import org.bukkit.enchantments.Enchantment;
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
+import su.nightexpress.nightcore.command.experimental.flag.CommandFlag;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class ParsedArguments {
+
+ private final Map> argumentMap;
+ private final Map> flags;
+
+ public ParsedArguments() {
+ this.argumentMap = new HashMap<>();
+ this.flags = new HashMap<>();
+ }
+
+ public void add(@NotNull CommandArgument> argument, @NotNull ParsedArgument> parsedArgument) {
+ this.argumentMap.put(argument.getName(), parsedArgument);
+ }
+
+ public void addFlag(@NotNull CommandFlag flag, @NotNull ParsedArgument> content) {
+ this.flags.put(flag.getName(), content);
+ }
+
+ @NotNull
+ public Map> getArgumentMap() {
+ return argumentMap;
+ }
+
+ @NotNull
+ public Map> getFlags() {
+ return flags;
+ }
+
+ public int getIntArgument(@NotNull String name, int defaultValue) {
+ return this.getArgument(name, Integer.class, defaultValue);
+ }
+
+ public int getIntArgument(@NotNull String name) {
+ return this.getArgument(name, Integer.class);
+ }
+
+ public double getDoubleArgument(@NotNull String name, double defaultValue) {
+ return this.getArgument(name, Double.class, defaultValue);
+ }
+
+ public double getDoubleArgument(@NotNull String name) {
+ return this.getArgument(name, Double.class);
+ }
+
+ public boolean getBooleanArgument(@NotNull String name, boolean defaultValue) {
+ return this.getArgument(name, Boolean.class, defaultValue);
+ }
+
+ public boolean getBooleanArgument(@NotNull String name) {
+ return this.getArgument(name, Boolean.class);
+ }
+
+ @NotNull
+ public String getStringArgument(@NotNull String name, @NotNull String defaultValue) {
+ return this.getArgument(name, String.class, defaultValue);
+ }
+
+ @NotNull
+ public String getStringArgument(@NotNull String name) {
+ return this.getArgument(name, String.class);
+ }
+
+ @NotNull
+ public Material getMaterialArgument(@NotNull String name, @NotNull Material defaultValue) {
+ return this.getArgument(name, Material.class, defaultValue);
+ }
+
+ @NotNull
+ public Material getMaterialArgument(@NotNull String name) {
+ return this.getArgument(name, Material.class);
+ }
+
+ @NotNull
+ public World getWorldArgument(@NotNull String name, @NotNull World defaultValue) {
+ return this.getArgument(name, World.class, defaultValue);
+ }
+
+ @NotNull
+ public World getWorldArgument(@NotNull String name) {
+ return this.getArgument(name, World.class);
+ }
+
+ @NotNull
+ public Enchantment getEnchantmentArgument(@NotNull String name, @NotNull Enchantment defaultValue) {
+ return this.getArgument(name, Enchantment.class, defaultValue);
+ }
+
+ @NotNull
+ public Enchantment getEnchantmentArgument(@NotNull String name) {
+ return this.getArgument(name, Enchantment.class);
+ }
+
+ @NotNull
+ public Player getPlayerArgument(@NotNull String name) {
+ return this.getArgument(name, Player.class);
+ }
+
+ public boolean hasArgument(@NotNull String name) {
+ return this.argumentMap.containsKey(name);
+ }
+
+ @NotNull
+ public T getArgument(@NotNull String name, @NotNull Class clazz, @NotNull T defaultValue) {
+ if (!this.hasArgument(name)) return defaultValue;
+
+ return this.getArgument(name, clazz);
+ }
+
+ @NotNull
+ public T getArgument(@NotNull String name, @NotNull Class clazz) {
+ ParsedArgument> argument = this.argumentMap.get(name);
+ if (argument == null) {
+ throw new IllegalArgumentException("No such argument '" + name + "' exists on this command");
+ }
+
+ Object result = argument.getResult();
+ if (clazz.isAssignableFrom(result.getClass())) {
+ return clazz.cast(result);
+ }
+ else {
+ throw new IllegalArgumentException("Argument '" + name + "' is defined as " + result.getClass().getSimpleName() + ", not " + clazz);
+ }
+ }
+
+ public boolean hasFlag(@NotNull CommandFlag flag) {
+ return this.hasFlag(flag.getName());
+ }
+
+ public boolean hasFlag(@NotNull String name) {
+ return this.flags.containsKey(name);
+ }
+
+ public int getIntFlag(@NotNull String name, int defaultValue) {
+ return this.getFlag(name, Integer.class, defaultValue);
+ }
+
+ public double getDoubleFlag(@NotNull String name, double defaultValue) {
+ return this.getFlag(name, Double.class, defaultValue);
+ }
+
+ public boolean getBooleanFlag(@NotNull String name, boolean defaultValue) {
+ return this.getFlag(name, Boolean.class, defaultValue);
+ }
+
+ @NotNull
+ public String getStringFlag(@NotNull String name, @NotNull String defaultValue) {
+ return this.getFlag(name, String.class, defaultValue);
+ }
+
+ @NotNull
+ public T getFlag(@NotNull String name, @NotNull Class clazz, @NotNull T defaultValue) {
+ if (!this.hasFlag(name)) return defaultValue;
+
+ return this.getFlag(name, clazz);
+ }
+
+ @NotNull
+ public T getFlag(@NotNull String name, @NotNull Class clazz) {
+ ParsedArgument> parsed = this.flags.get(name);
+ if (parsed == null) {
+ throw new IllegalArgumentException("No such flag '" + name + "' exists on this command");
+ }
+
+ Object result = parsed.getResult();
+ if (clazz.isAssignableFrom(result.getClass())) {
+ return clazz.cast(result);
+ }
+ else {
+ throw new IllegalArgumentException("Flag '" + name + "' is defined as " + result.getClass().getSimpleName() + ", not " + clazz);
+ }
+ }
+}
diff --git a/src/main/java/su/nightexpress/nightcore/command/experimental/builder/ArgumentBuilder.java b/src/main/java/su/nightexpress/nightcore/command/experimental/builder/ArgumentBuilder.java
new file mode 100644
index 0000000..b0c65e8
--- /dev/null
+++ b/src/main/java/su/nightexpress/nightcore/command/experimental/builder/ArgumentBuilder.java
@@ -0,0 +1,85 @@
+package su.nightexpress.nightcore.command.experimental.builder;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import su.nightexpress.nightcore.command.experimental.TabContext;
+import su.nightexpress.nightcore.command.experimental.argument.CommandArgument;
+import su.nightexpress.nightcore.language.entry.LangString;
+import su.nightexpress.nightcore.language.entry.LangText;
+import su.nightexpress.nightcore.language.message.LangMessage;
+import su.nightexpress.nightcore.util.wrapper.UniPermission;
+
+import java.util.List;
+import java.util.function.Function;
+
+public class ArgumentBuilder {
+
+ private final String name;
+ private final Function parser;
+
+ private boolean required;
+ private String localized;
+ private String permission;
+ private Function> samples;
+ private LangMessage failureMessage;
+
+ public ArgumentBuilder(@NotNull String name, @NotNull Function parser) {
+ this.name = name;
+ this.parser = parser;
+ }
+
+ @NotNull
+ public ArgumentBuilder required() {
+ return this.required(true);
+ }
+
+ @NotNull
+ public ArgumentBuilder required(boolean required) {
+ this.required = required;
+ return this;
+ }
+
+ @NotNull
+ public ArgumentBuilder localized(@NotNull LangString localized) {
+ return this.localized(localized.getString());
+ }
+
+ @NotNull
+ public ArgumentBuilder localized(@Nullable String localized) {
+ this.localized = localized;
+ return this;
+ }
+
+ @NotNull
+ public ArgumentBuilder permission(@NotNull UniPermission permission) {
+ return this.permission(permission.getName());
+ }
+
+ @NotNull
+ public ArgumentBuilder permission(@Nullable String permission) {
+ this.permission = permission;
+ return this;
+ }
+
+ @NotNull
+ public ArgumentBuilder customFailure(@NotNull LangText text) {
+ return this.customFailure(text.getMessage());
+ }
+
+ @NotNull
+ public ArgumentBuilder customFailure(@Nullable LangMessage message) {
+ this.failureMessage = message;
+ return this;
+ }
+
+ @NotNull
+ public ArgumentBuilder withSamples(@NotNull Function> samples) {
+ this.samples = samples;
+ return this;
+ }
+
+ @NotNull
+ public CommandArgument build() {
+ return new CommandArgument<>(this.name, this.parser, this.required, this.localized, this.permission, this.failureMessage, this.samples);
+ }
+}
diff --git a/src/main/java/su/nightexpress/nightcore/command/experimental/builder/ChainedNodeBuilder.java b/src/main/java/su/nightexpress/nightcore/command/experimental/builder/ChainedNodeBuilder.java
new file mode 100644
index 0000000..9a29dd5
--- /dev/null
+++ b/src/main/java/su/nightexpress/nightcore/command/experimental/builder/ChainedNodeBuilder.java
@@ -0,0 +1,82 @@
+package su.nightexpress.nightcore.command.experimental.builder;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import su.nightexpress.nightcore.NightCorePlugin;
+import su.nightexpress.nightcore.command.experimental.node.NodeExecutor;
+import su.nightexpress.nightcore.command.experimental.node.ChainedNode;
+import su.nightexpress.nightcore.command.experimental.node.CommandNode;
+import su.nightexpress.nightcore.command.experimental.node.DirectNode;
+import su.nightexpress.nightcore.language.entry.LangString;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.function.Consumer;
+
+public class ChainedNodeBuilder extends NodeBuilder {
+
+ private final Map childrenMap;
+
+ private String localized;
+ private NodeExecutor executor;
+
+ public ChainedNodeBuilder(@NotNull NightCorePlugin plugin, @NotNull String... aliases) {
+ super(plugin, aliases);
+ this.childrenMap = new HashMap<>();
+ }
+
+ @Override
+ @NotNull
+ protected ChainedNodeBuilder getThis() {
+ return this;
+ }
+
+ @NotNull
+ public ChainedNodeBuilder localized(@NotNull LangString localized) {
+ return this.localized(localized.getString());
+ }
+
+ @NotNull
+ public ChainedNodeBuilder localized(@Nullable String localized) {
+ this.localized = localized;
+ return this;
+ }
+
+ @NotNull
+ public ChainedNodeBuilder addChained(@NotNull String name, @NotNull Consumer consumer) {
+ ChainedNodeBuilder builder = ChainedNode.builder(this.plugin, name);
+ consumer.accept(builder);
+ return this.child(builder);
+ }
+
+ @NotNull
+ public ChainedNodeBuilder addDirect(@NotNull String name, @NotNull Consumer consumer) {
+ DirectNodeBuilder builder = DirectNode.builder(this.plugin, name);
+ consumer.accept(builder);
+ return this.child(builder);
+ }
+
+ @NotNull
+ public > ChainedNodeBuilder child(@NotNull B builder) {
+ return this.child(builder.build());
+ }
+
+ @NotNull
+ private ChainedNodeBuilder child(@NotNull CommandNode name) {
+ this.childrenMap.put(name.getName(), name);
+ return this;
+ }
+
+ @NotNull
+ public ChainedNodeBuilder fallback(@NotNull NodeExecutor executor) {
+ this.executor = executor;
+ return this;
+ }
+
+ @Override
+ @NotNull
+ public ChainedNode build() {
+ return new ChainedNode(this.plugin, this.name, this.aliases, this.description, this.localized, this.permission, this.playerOnly,
+ this.executor, this.childrenMap);
+ }
+}
diff --git a/src/main/java/su/nightexpress/nightcore/command/experimental/builder/ContentFlagBuilder.java b/src/main/java/su/nightexpress/nightcore/command/experimental/builder/ContentFlagBuilder.java
new file mode 100644
index 0000000..e5f06b6
--- /dev/null
+++ b/src/main/java/su/nightexpress/nightcore/command/experimental/builder/ContentFlagBuilder.java
@@ -0,0 +1,36 @@
+package su.nightexpress.nightcore.command.experimental.builder;
+
+import org.jetbrains.annotations.NotNull;
+import su.nightexpress.nightcore.command.experimental.flag.ContentFlag;
+
+import java.util.function.Function;
+
+public class ContentFlagBuilder extends FlagBuilder, ContentFlagBuilder> {
+
+ private final Function parser;
+
+ private String sample;
+
+ public ContentFlagBuilder(@NotNull String name, @NotNull Function parser) {
+ super(name);
+ this.parser = parser;
+ this.sample = "";
+ }
+
+ @Override
+ @NotNull
+ protected ContentFlagBuilder getThis() {
+ return this;
+ }
+
+ @NotNull
+ public ContentFlagBuilder sample(@NotNull String sample) {
+ this.sample = sample;
+ return getThis();
+ }
+
+ @Override
+ public @NotNull ContentFlag build() {
+ return new ContentFlag<>(this.name, this.parser, this.sample, this.permission);
+ }
+}
diff --git a/src/main/java/su/nightexpress/nightcore/command/experimental/builder/DirectNodeBuilder.java b/src/main/java/su/nightexpress/nightcore/command/experimental/builder/DirectNodeBuilder.java
new file mode 100644
index 0000000..a7d3506
--- /dev/null
+++ b/src/main/java/su/nightexpress/nightcore/command/experimental/builder/DirectNodeBuilder.java
@@ -0,0 +1,67 @@
+package su.nightexpress.nightcore.command.experimental.builder;
+
+import org.jetbrains.annotations.NotNull;
+import su.nightexpress.nightcore.NightCorePlugin;
+import su.nightexpress.nightcore.command.experimental.argument.CommandArgument;
+import su.nightexpress.nightcore.command.experimental.flag.CommandFlag;
+import su.nightexpress.nightcore.command.experimental.node.DirectExecutor;
+import su.nightexpress.nightcore.command.experimental.node.DirectNode;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class DirectNodeBuilder extends NodeBuilder {
+
+ private final List> arguments;
+ private final Map flags;
+
+ private DirectExecutor executor;
+
+ public DirectNodeBuilder(@NotNull NightCorePlugin plugin, @NotNull String... aliases) {
+ super(plugin, aliases);
+ this.arguments = new ArrayList<>();
+ this.flags = new HashMap<>();
+ }
+
+ @Override
+ @NotNull
+ protected DirectNodeBuilder getThis() {
+ return this;
+ }
+
+ @NotNull
+ public DirectNodeBuilder withArgument(@NotNull ArgumentBuilder> builder) {
+ return this.withArgument(builder.build());
+ }
+
+ @NotNull
+ public DirectNodeBuilder withArgument(@NotNull CommandArgument> argument) {
+ this.arguments.add(argument);
+ return this;
+ }
+
+ @NotNull
+ public DirectNodeBuilder withFlag(@NotNull FlagBuilder, ?> builder) {
+ return this.withFlag(builder.build());
+ }
+
+ @NotNull
+ public DirectNodeBuilder withFlag(@NotNull CommandFlag flag) {
+ this.flags.put(flag.getName(), flag);
+ return this;
+ }
+
+ @NotNull
+ public DirectNodeBuilder executes(DirectExecutor executor) {
+ this.executor = executor;
+ return this;
+ }
+
+ @Override
+ @NotNull
+ public DirectNode build() {
+ return new DirectNode(this.plugin, this.name, this.aliases, this.description, this.permission, this.playerOnly, this.arguments, this.flags, this.executor);
+ }
+}
diff --git a/src/main/java/su/nightexpress/nightcore/command/experimental/builder/FlagBuilder.java b/src/main/java/su/nightexpress/nightcore/command/experimental/builder/FlagBuilder.java
new file mode 100644
index 0000000..6670ebd
--- /dev/null
+++ b/src/main/java/su/nightexpress/nightcore/command/experimental/builder/FlagBuilder.java
@@ -0,0 +1,34 @@
+package su.nightexpress.nightcore.command.experimental.builder;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import su.nightexpress.nightcore.command.experimental.flag.CommandFlag;
+import su.nightexpress.nightcore.util.wrapper.UniPermission;
+
+public abstract class FlagBuilder> {
+
+ protected final String name;
+
+ protected String permission;
+
+ public FlagBuilder(@NotNull String name) {
+ this.name = name;
+ }
+
+ @NotNull
+ protected abstract FlagBuilder getThis();
+
+ @NotNull
+ public FlagBuilder permission(@NotNull UniPermission permission) {
+ return this.permission(permission.getName());
+ }
+
+ @NotNull
+ public FlagBuilder permission(@Nullable String permission) {
+ this.permission = permission;
+ return this.getThis();
+ }
+
+ @NotNull
+ public abstract F build();
+}
diff --git a/src/main/java/su/nightexpress/nightcore/command/experimental/builder/NodeBuilder.java b/src/main/java/su/nightexpress/nightcore/command/experimental/builder/NodeBuilder.java
new file mode 100644
index 0000000..3b447ab
--- /dev/null
+++ b/src/main/java/su/nightexpress/nightcore/command/experimental/builder/NodeBuilder.java
@@ -0,0 +1,70 @@
+package su.nightexpress.nightcore.command.experimental.builder;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import su.nightexpress.nightcore.NightCorePlugin;
+import su.nightexpress.nightcore.command.experimental.node.CommandNode;
+import su.nightexpress.nightcore.language.entry.LangString;
+import su.nightexpress.nightcore.util.wrapper.UniPermission;
+
+import java.util.stream.Stream;
+
+public abstract class NodeBuilder> {
+
+ protected final NightCorePlugin plugin;
+ protected final String name;
+
+ protected String[] aliases;
+ protected String description;
+ protected String permission;
+ protected boolean playerOnly;
+
+ public NodeBuilder(@NotNull NightCorePlugin plugin, @NotNull String... aliases) {
+ this.plugin = plugin;
+ this.name = aliases[0];
+ this.aliases = Stream.of(aliases).skip(1).toArray(String[]::new);
+ this.description = "";
+ this.permission = null;
+ this.playerOnly = false;
+ }
+
+ @NotNull
+ protected abstract B getThis();
+
+ @NotNull
+ public abstract S build();
+
+ @NotNull
+ public B aliases(@NotNull String... aliases) {
+ this.aliases = aliases;
+ return this.getThis();
+ }
+
+ @NotNull
+ public B description(@NotNull LangString description) {
+ return this.description(description.getString());
+ }
+
+ @NotNull
+ public B description(@NotNull String description) {
+ this.description = description;
+ return this.getThis();
+ }
+
+ @NotNull
+ public B permission(@NotNull UniPermission permission) {
+ return this.permission(permission.getName());
+ }
+
+ @NotNull
+ public B permission(@Nullable String permission) {
+ this.permission = permission;
+ return this.getThis();
+ }
+
+ @NotNull
+ public B playerOnly() {
+ this.playerOnly = true;
+ return this.getThis();
+ }
+}
diff --git a/src/main/java/su/nightexpress/nightcore/command/experimental/builder/SimpleFlagBuilder.java b/src/main/java/su/nightexpress/nightcore/command/experimental/builder/SimpleFlagBuilder.java
new file mode 100644
index 0000000..eba538c
--- /dev/null
+++ b/src/main/java/su/nightexpress/nightcore/command/experimental/builder/SimpleFlagBuilder.java
@@ -0,0 +1,23 @@
+package su.nightexpress.nightcore.command.experimental.builder;
+
+import org.jetbrains.annotations.NotNull;
+import su.nightexpress.nightcore.command.experimental.flag.SimpleFlag;
+
+public class SimpleFlagBuilder extends FlagBuilder {
+
+ public SimpleFlagBuilder(@NotNull String name) {
+ super(name);
+ }
+
+ @Override
+ @NotNull
+ protected SimpleFlagBuilder getThis() {
+ return this;
+ }
+
+ @Override
+ @NotNull
+ public SimpleFlag build() {
+ return new SimpleFlag(this.name, this.permission);
+ }
+}
diff --git a/src/main/java/su/nightexpress/nightcore/command/experimental/flag/CommandFlag.java b/src/main/java/su/nightexpress/nightcore/command/experimental/flag/CommandFlag.java
new file mode 100644
index 0000000..13a8211
--- /dev/null
+++ b/src/main/java/su/nightexpress/nightcore/command/experimental/flag/CommandFlag.java
@@ -0,0 +1,52 @@
+package su.nightexpress.nightcore.command.experimental.flag;
+
+import org.bukkit.command.CommandSender;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import su.nightexpress.nightcore.core.CoreLang;
+import su.nightexpress.nightcore.util.Placeholders;
+
+public abstract class CommandFlag {
+
+ public static final char PREFIX = '-';
+ public static final char DELIMITER = '=';
+
+ private final String name;
+ private final String permission;
+
+ public CommandFlag(@NotNull String name, @Nullable String permission) {
+ this.name = name.toLowerCase();
+ this.permission = permission;
+ }
+
+ public boolean hasPermission(@NotNull CommandSender sender) {
+ return this.permission == null || sender.hasPermission(this.permission);
+ }
+
+ @NotNull
+ public String getName() {
+ return name;
+ }
+
+ @NotNull
+ public String getPrefixed() {
+ return PREFIX + this.getName();
+ }
+
+ @NotNull
+ public String getPrefixedFormatted() {
+ return CoreLang.COMMAND_FLAG_FORMAT.getString().replace(Placeholders.GENERIC_NAME, this.getPrefixed());
+ }
+
+ @Nullable
+ public String getPermission() {
+ return permission;
+ }
+
+ @Override
+ public String toString() {
+ return "CommandFlag{" +
+ "name='" + name + '\'' +
+ '}';
+ }
+}
diff --git a/src/main/java/su/nightexpress/nightcore/command/experimental/flag/ContentFlag.java b/src/main/java/su/nightexpress/nightcore/command/experimental/flag/ContentFlag.java
new file mode 100644
index 0000000..f9882ae
--- /dev/null
+++ b/src/main/java/su/nightexpress/nightcore/command/experimental/flag/ContentFlag.java
@@ -0,0 +1,46 @@
+package su.nightexpress.nightcore.command.experimental.flag;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import su.nightexpress.nightcore.command.experimental.argument.ParsedArgument;
+import su.nightexpress.nightcore.command.experimental.builder.ContentFlagBuilder;
+
+import java.util.function.Function;
+
+public class ContentFlag extends CommandFlag {
+
+ private final Function parser;
+ private final String sample;
+
+ public ContentFlag(@NotNull String name, @NotNull Function parser, @Nullable String sample, @Nullable String permission) {
+ super(name, permission);
+ this.parser = parser;
+ this.sample = sample == null ? "" : sample;
+ }
+
+ @NotNull
+ public static ContentFlagBuilder builder(@NotNull String name, @NotNull Function parser) {
+ return new ContentFlagBuilder<>(name, parser);
+ }
+
+ @Nullable
+ public ParsedArgument parse(@NotNull String str) {
+ T result = this.parser.apply(str);
+ return result == null ? null : new ParsedArgument<>(result);
+ }
+
+ @NotNull
+ public String getSampled() {
+ return this.getPrefixed() + DELIMITER + this.getSample();
+ }
+
+ @NotNull
+ public Function getParser() {
+ return parser;
+ }
+
+ @NotNull
+ public String getSample() {
+ return sample;
+ }
+}
diff --git a/src/main/java/su/nightexpress/nightcore/command/experimental/flag/FlagTypes.java b/src/main/java/su/nightexpress/nightcore/command/experimental/flag/FlagTypes.java
new file mode 100644
index 0000000..52a5b72
--- /dev/null
+++ b/src/main/java/su/nightexpress/nightcore/command/experimental/flag/FlagTypes.java
@@ -0,0 +1,40 @@
+package su.nightexpress.nightcore.command.experimental.flag;
+
+import org.bukkit.World;
+import org.jetbrains.annotations.NotNull;
+import su.nightexpress.nightcore.command.experimental.argument.ArgumentTypes;
+import su.nightexpress.nightcore.command.experimental.builder.ContentFlagBuilder;
+import su.nightexpress.nightcore.command.experimental.builder.SimpleFlagBuilder;
+
+public class FlagTypes {
+
+ @NotNull
+ public static SimpleFlagBuilder simple(@NotNull String name) {
+ return SimpleFlag.builder(name);
+ }
+
+ @NotNull
+ public static ContentFlagBuilder world(@NotNull String name) {
+ return ContentFlag.builder(name, ArgumentTypes.WORLD).sample("world");
+ }
+
+ @NotNull
+ public static ContentFlagBuilder string(@NotNull String name) {
+ return ContentFlag.builder(name, ArgumentTypes.STRING).sample("foo");
+ }
+
+ @NotNull
+ public static ContentFlagBuilder integer(@NotNull String name) {
+ return ContentFlag.builder(name, ArgumentTypes.INTEGER).sample("0");
+ }
+
+ @NotNull
+ public static ContentFlagBuilder decimal(@NotNull String name) {
+ return ContentFlag.builder(name, ArgumentTypes.DOUBLE).sample("0.0");
+ }
+
+ @NotNull
+ public static ContentFlagBuilder bool(@NotNull String name) {
+ return ContentFlag.builder(name, ArgumentTypes.BOOLEAN).sample(Boolean.TRUE.toString());
+ }
+}
diff --git a/src/main/java/su/nightexpress/nightcore/command/experimental/flag/SimpleFlag.java b/src/main/java/su/nightexpress/nightcore/command/experimental/flag/SimpleFlag.java
new file mode 100644
index 0000000..3fd821f
--- /dev/null
+++ b/src/main/java/su/nightexpress/nightcore/command/experimental/flag/SimpleFlag.java
@@ -0,0 +1,17 @@
+package su.nightexpress.nightcore.command.experimental.flag;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import su.nightexpress.nightcore.command.experimental.builder.SimpleFlagBuilder;
+
+public class SimpleFlag extends CommandFlag {
+
+ public SimpleFlag(@NotNull String name, @Nullable String permission) {
+ super(name, permission);
+ }
+
+ @NotNull
+ public static SimpleFlagBuilder builder(@NotNull String name) {
+ return new SimpleFlagBuilder(name);
+ }
+}
diff --git a/src/main/java/su/nightexpress/nightcore/command/experimental/impl/ReloadCommand.java b/src/main/java/su/nightexpress/nightcore/command/experimental/impl/ReloadCommand.java
new file mode 100644
index 0000000..bfcfef8
--- /dev/null
+++ b/src/main/java/su/nightexpress/nightcore/command/experimental/impl/ReloadCommand.java
@@ -0,0 +1,26 @@
+package su.nightexpress.nightcore.command.experimental.impl;
+
+import org.jetbrains.annotations.NotNull;
+import su.nightexpress.nightcore.NightCorePlugin;
+import su.nightexpress.nightcore.command.experimental.CommandContext;
+import su.nightexpress.nightcore.command.experimental.argument.ParsedArguments;
+import su.nightexpress.nightcore.command.experimental.node.ChainedNode;
+import su.nightexpress.nightcore.command.experimental.node.DirectNode;
+import su.nightexpress.nightcore.core.CoreLang;
+import su.nightexpress.nightcore.util.wrapper.UniPermission;
+
+public class ReloadCommand {
+
+ public static void inject(@NotNull NightCorePlugin plugin, @NotNull ChainedNode node, @NotNull UniPermission permission) {
+ node.addChildren(DirectNode.builder(plugin, "reload")
+ .permission(permission)
+ .description(CoreLang.COMMAND_RELOAD_DESC)
+ .executes((context, arguments) -> execute(plugin, context, arguments))
+ );
+ }
+
+ public static boolean execute(@NotNull NightCorePlugin plugin, @NotNull CommandContext context, @NotNull ParsedArguments arguments) {
+ plugin.reload();
+ return context.sendSuccess(CoreLang.COMMAND_RELOAD_DONE.getMessage(plugin));
+ }
+}
diff --git a/src/main/java/su/nightexpress/nightcore/command/experimental/node/ChainedNode.java b/src/main/java/su/nightexpress/nightcore/command/experimental/node/ChainedNode.java
new file mode 100644
index 0000000..399e9d9
--- /dev/null
+++ b/src/main/java/su/nightexpress/nightcore/command/experimental/node/ChainedNode.java
@@ -0,0 +1,157 @@
+package su.nightexpress.nightcore.command.experimental.node;
+
+import org.bukkit.command.CommandSender;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import su.nightexpress.nightcore.NightCorePlugin;
+import su.nightexpress.nightcore.command.experimental.CommandContext;
+import su.nightexpress.nightcore.command.experimental.TabContext;
+import su.nightexpress.nightcore.command.experimental.builder.ChainedNodeBuilder;
+import su.nightexpress.nightcore.command.experimental.builder.NodeBuilder;
+import su.nightexpress.nightcore.core.CoreLang;
+import su.nightexpress.nightcore.util.Placeholders;
+import su.nightexpress.nightcore.util.StringUtil;
+
+import java.util.*;
+
+public class ChainedNode extends CommandNode {
+
+ private final String localized;
+ private final Map commandMap;
+ private final NodeExecutor fallback;
+
+ public ChainedNode(@NotNull NightCorePlugin plugin,
+ @NotNull String name,
+ @NotNull String[] aliases,
+ @NotNull String description,
+ @Nullable String localized,
+ @Nullable String permission,
+ boolean playerOnly,
+ @Nullable NodeExecutor fallback,
+ @NotNull Map commandMap) {
+ super(plugin, name, aliases, description, permission, playerOnly);
+ this.localized = localized == null ? StringUtil.capitalizeUnderscored(name) : localized;
+ this.commandMap = new HashMap<>();
+ this.fallback = fallback;
+
+ this.addChildren(DirectNode.builder(plugin, "help")
+ .description(CoreLang.COMMAND_HELP_DESC)
+ .permission(permission)
+ .executes((context, arguments) -> this.sendCommandList(context))
+ );
+
+ commandMap.values().forEach(this::addChildren);
+ }
+
+ @NotNull
+ public static ChainedNodeBuilder builder(@NotNull NightCorePlugin plugin, @NotNull String... aliases) {
+ return new ChainedNodeBuilder(plugin, aliases);
+ }
+
+ @Override
+ protected boolean onRun(@NotNull CommandContext context) {
+ //System.out.println("context.getArgs() = " + Arrays.toString(context.getArgs()));
+ if (context.getArgs().length == 0 || context.getArgumentIndex() >= context.getArgs().length) {
+ return this.onFallback(context);
+ }
+
+ String node = context.getArgs()[context.getArgumentIndex()];
+ //System.out.println("node = " + node);
+ CommandNode children = this.getCommandMap().get(node);
+ //System.out.println("children = " + children);
+ //System.out.println("this.commandMap = " + this.commandMap);
+ if (children == null) {
+ return this.onFallback(context);
+ }
+
+ //System.out.println("children run");
+ context.setArgumentIndex(context.getArgumentIndex() + 1);
+ return children.run(context);
+ }
+
+ private boolean onFallback(@NotNull CommandContext context) {
+ if (this.fallback != null) {
+ return this.fallback.run(context);
+ }
+ return this.sendCommandList(context);
+ }
+
+ private boolean sendCommandList(@NotNull CommandContext context) {
+ CommandSender sender = context.getSender();
+
+ return context.sendSuccess(CoreLang.COMMAND_HELP_LIST.getMessage()
+ .replace(Placeholders.GENERIC_NAME, this.getLocalized())
+ .replace(Placeholders.GENERIC_ENTRY, list -> {
+ this.getChildrens().stream().sorted(Comparator.comparing(CommandNode::getName)).forEach(children -> {
+ if (!children.hasPermission(sender)) return;
+
+ list.add(CoreLang.COMMAND_HELP_ENTRY.getString()
+ .replace(Placeholders.COMMAND_LABEL, children.getNameWithParents())
+ .replace(Placeholders.COMMAND_USAGE, children.getUsage())
+ .replace(Placeholders.COMMAND_DESCRIPTION, children.getDescription())
+ );
+ });
+ }));
+ }
+
+ @Override
+ @NotNull
+ public List getTab(@NotNull TabContext context) {
+ //System.out.println("context.getArgs() = " + Arrays.toString(context.getArgs()));
+ //System.out.println("context.getIndex() = " + context.getIndex());
+ if (context.getIndex() == context.getArgs().length - 1) {
+ return new ArrayList<>(this.commandMap.keySet());
+ }
+ if (context.getIndex() >= context.getArgs().length) {
+ return Collections.emptyList();
+ }
+
+ String node = context.getAtIndex();
+ CommandNode children = this.getCommandMap().get(node);
+ if (children == null) {
+ return Collections.emptyList();
+ }
+
+ context.setIndex(context.getIndex() + 1);
+
+ return children.getTab(context);
+ }
+
+ public void addChildren(@NotNull NodeBuilder, ?> builder) {
+ this.addChildren(builder.build());
+ }
+
+ public void addChildren(@NotNull CommandNode children) {
+ if (children.getParent() != null) return;
+
+ this.commandMap.put(children.getName(), children);
+ for (String alias : children.getAliases()) {
+ this.commandMap.put(alias, children);
+ }
+ children.setParent(this);
+ }
+
+ public void removeChildren(@NotNull String alias) {
+ this.commandMap.keySet().removeIf(key -> key.equalsIgnoreCase(alias));
+ }
+
+ @Nullable
+ public CommandNode getChildren(@NotNull String alias) {
+ return this.commandMap.get(alias);
+ }
+
+ @NotNull
+ public Set getChildrens() {
+ return new HashSet<>(this.commandMap.values());
+ }
+
+ @NotNull
+ public String getLocalized() {
+ return localized;
+ }
+
+ @NotNull
+ public Map getCommandMap() {
+ return commandMap;
+ }
+}
diff --git a/src/main/java/su/nightexpress/nightcore/command/experimental/node/CommandNode.java b/src/main/java/su/nightexpress/nightcore/command/experimental/node/CommandNode.java
new file mode 100644
index 0000000..2ca56b9
--- /dev/null
+++ b/src/main/java/su/nightexpress/nightcore/command/experimental/node/CommandNode.java
@@ -0,0 +1,117 @@
+package su.nightexpress.nightcore.command.experimental.node;
+
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import su.nightexpress.nightcore.NightCorePlugin;
+import su.nightexpress.nightcore.command.experimental.CommandContext;
+import su.nightexpress.nightcore.command.experimental.TabContext;
+
+import java.util.List;
+import java.util.stream.Stream;
+
+public abstract class CommandNode implements NodeExecutor {
+
+ protected final NightCorePlugin plugin;
+ protected final String name;
+ protected final String[] aliases;
+ protected final String description;
+ protected final String permission;
+ protected final boolean playerOnly;
+
+ protected CommandNode parent;
+
+ public CommandNode(@NotNull NightCorePlugin plugin,
+ @NotNull String name,
+ @NotNull String[] aliases,
+ @NotNull String description,
+ @Nullable String permission,
+ boolean playerOnly) {
+ this.plugin = plugin;
+ this.name = name.toLowerCase();
+ this.aliases = Stream.of(aliases).map(String::toLowerCase).toArray(String[]::new);
+ this.description = description;
+ this.permission = permission;
+ this.playerOnly = playerOnly;
+ }
+
+ @NotNull
+ public abstract List getTab(@NotNull TabContext context);
+
+ @Override
+ public boolean run(@NotNull CommandContext context) {
+ if (this.isPlayerOnly() && !(context.getSender() instanceof Player)) {
+ context.errorPlayerOnly();
+ return false;
+ }
+ if (!this.hasPermission(context.getSender())) {
+ context.errorPermission();
+ return false;
+ }
+
+ return this.onRun(context);
+ }
+
+ protected abstract boolean onRun(@NotNull CommandContext context);
+
+ public boolean hasPermission(@NotNull CommandSender sender) {
+ return this.permission == null || sender.hasPermission(this.permission);
+ }
+
+ @NotNull
+ public String getNameWithParents() {
+ StringBuilder builder = new StringBuilder();
+
+ CommandNode parent = this.getParent();
+ while (parent != null) {
+ if (!builder.isEmpty()) {
+ builder.insert(0, " ");
+ }
+ builder.insert(0, parent.getName());
+ parent = parent.getParent();
+ }
+
+ builder.append(" ").append(this.getName());
+
+ return builder.toString().strip();
+ }
+
+ @NotNull
+ public String getName() {
+ return name;
+ }
+
+ @NotNull
+ public String[] getAliases() {
+ return this.aliases;
+ }
+
+ @NotNull
+ public String getUsage() {
+ return "";
+ }
+
+ @NotNull
+ public String getDescription() {
+ return description;
+ }
+
+ @Nullable
+ public CommandNode getParent() {
+ return parent;
+ }
+
+ protected void setParent(@Nullable CommandNode parent) {
+ this.parent = parent;
+ }
+
+ @Nullable
+ public String getPermission() {
+ return permission;
+ }
+
+ public boolean isPlayerOnly() {
+ return this.playerOnly;
+ }
+}
diff --git a/src/main/java/su/nightexpress/nightcore/command/experimental/node/DirectExecutor.java b/src/main/java/su/nightexpress/nightcore/command/experimental/node/DirectExecutor.java
new file mode 100644
index 0000000..67eea03
--- /dev/null
+++ b/src/main/java/su/nightexpress/nightcore/command/experimental/node/DirectExecutor.java
@@ -0,0 +1,10 @@
+package su.nightexpress.nightcore.command.experimental.node;
+
+import org.jetbrains.annotations.NotNull;
+import su.nightexpress.nightcore.command.experimental.CommandContext;
+import su.nightexpress.nightcore.command.experimental.argument.ParsedArguments;
+
+public interface DirectExecutor {
+
+ boolean execute(@NotNull CommandContext context, @NotNull ParsedArguments arguments);
+}
diff --git a/src/main/java/su/nightexpress/nightcore/command/experimental/node/DirectNode.java b/src/main/java/su/nightexpress/nightcore/command/experimental/node/DirectNode.java
new file mode 100644
index 0000000..1e84e6e
--- /dev/null
+++ b/src/main/java/su/nightexpress/nightcore/command/experimental/node/DirectNode.java
@@ -0,0 +1,197 @@
+package su.nightexpress.nightcore.command.experimental.node;
+
+import org.bukkit.command.CommandSender;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import su.nightexpress.nightcore.NightCorePlugin;
+import su.nightexpress.nightcore.command.experimental.argument.CommandArgument;
+import su.nightexpress.nightcore.command.experimental.CommandContext;
+import su.nightexpress.nightcore.command.experimental.argument.ParsedArgument;
+import su.nightexpress.nightcore.command.experimental.argument.ParsedArguments;
+import su.nightexpress.nightcore.command.experimental.TabContext;
+import su.nightexpress.nightcore.command.experimental.builder.DirectNodeBuilder;
+import su.nightexpress.nightcore.command.experimental.flag.CommandFlag;
+import su.nightexpress.nightcore.command.experimental.flag.ContentFlag;
+import su.nightexpress.nightcore.core.CoreLang;
+import su.nightexpress.nightcore.util.Placeholders;
+
+import java.util.*;
+
+public class DirectNode extends CommandNode implements DirectExecutor {
+
+ private final List> arguments;
+ private final Map flags;
+ private final DirectExecutor executor;
+
+ private final int requiredArguments;
+
+ public DirectNode(@NotNull NightCorePlugin plugin,
+ @NotNull String name,
+ @NotNull String[] aliases,
+ @NotNull String description,
+ @Nullable String permission,
+ boolean playerOnly,
+ @NotNull List> arguments,
+ @NotNull Map flags,
+ @NotNull DirectExecutor executor) {
+ super(plugin, name, aliases, description, permission, playerOnly);
+ this.arguments = Collections.unmodifiableList(arguments);
+ this.flags = Collections.unmodifiableMap(flags);
+ this.executor = executor;
+ this.requiredArguments = (int) this.arguments.stream().filter(CommandArgument::isRequired).count();
+ }
+
+ @NotNull
+ public static DirectNodeBuilder builder(@NotNull NightCorePlugin plugin, @NotNull String... aliases) {
+ return new DirectNodeBuilder(plugin, aliases);
+ }
+
+ @Override
+ public boolean execute(@NotNull CommandContext context, @NotNull ParsedArguments arguments) {
+ return this.executor.execute(context, arguments);
+ }
+
+ @Override
+ protected boolean onRun(@NotNull CommandContext context) {
+ CommandSender sender = context.getSender();
+ String[] args = context.getArgs();
+ int index = context.getArgumentIndex();
+ //System.out.println("plaincmd args = " + Arrays.toString(args));
+ //System.out.println("plaincmd index = " + index);
+
+ ParsedArguments parsedArguments = new ParsedArguments();
+ for (CommandArgument> argument : this.arguments) {
+ if (index >= args.length) break;
+
+ if (!argument.hasPermission(sender)) {
+ context.errorPermission();
+ return false;
+ }
+
+ String arg = args[index++];
+ ParsedArgument> parsedArgument = argument.parse(arg);
+ if (parsedArgument == null) {
+ return context.sendFailure(argument.getFailureMessage()
+ .replace(Placeholders.GENERIC_VALUE, arg)
+ .replace(Placeholders.GENERIC_NAME, argument.getLocalized())
+ );
+ }
+
+ parsedArguments.add(argument, parsedArgument);
+ }
+
+ if (parsedArguments.getArgumentMap().size() < this.requiredArguments) {
+ return context.sendFailure(CoreLang.ERROR_COMMAND_USAGE.getMessage(this.plugin)
+ .replace(Placeholders.COMMAND_LABEL, this.getNameWithParents())
+ .replace(Placeholders.COMMAND_USAGE, this.getUsage()));
+ }
+
+ if (!this.flags.isEmpty() && index < args.length) {
+ for (int flagIndex = index; flagIndex < args.length; flagIndex++) {
+ String arg = args[flagIndex];
+ if (arg.charAt(0) != CommandFlag.PREFIX) continue;
+
+ int delimiterIndex = arg.indexOf(ContentFlag.DELIMITER);
+ boolean hasDelimiter = delimiterIndex != -1;
+
+ String flagName = (hasDelimiter ? arg.substring(0, delimiterIndex) : arg).substring(1);
+ CommandFlag flag = this.getFlag(flagName);
+ if (flag == null || parsedArguments.hasFlag(flag) || !flag.hasPermission(sender)) continue;
+
+ if (flag instanceof ContentFlag> contentFlag) {
+ if (!hasDelimiter) continue;
+
+ String content = arg.substring(delimiterIndex + 1);
+ if (content.isEmpty()) continue;
+
+ ParsedArgument> parsed = contentFlag.parse(content);
+ if (parsed == null) {
+ context.send(CoreLang.ERROR_COMMAND_PARSE_FLAG.getMessage()
+ .replace(Placeholders.GENERIC_VALUE, content)
+ .replace(Placeholders.GENERIC_NAME, flag.getName())
+ );
+ continue;
+ }
+
+ parsedArguments.addFlag(flag, parsed);
+ }
+ else {
+ parsedArguments.addFlag(flag, new ParsedArgument<>(true));
+ }
+ }
+ }
+
+ return this.execute(context, parsedArguments);
+ }
+
+ @Override
+ @NotNull
+ public List getTab(@NotNull TabContext context) {
+ int index = context.getArgs().length - (context.getIndex() + 1);
+ //System.out.println("index = " + index);
+ //System.out.println("arguments.size() = " + arguments.size());
+ if (index >= this.arguments.size()) {
+ List samples = new ArrayList<>();
+
+ this.getFlags().forEach(commandFlag -> {
+ if (!commandFlag.hasPermission(context.getSender())) return;
+ if (commandFlag instanceof ContentFlag> contentFlag) {
+ samples.add(contentFlag.getSampled());
+ }
+ else {
+ samples.add(commandFlag.getPrefixed());
+ }
+ });
+
+ return samples;
+ }
+
+ CommandArgument> argument = this.arguments.get(index);
+ if (!argument.hasPermission(context.getSender())) return Collections.emptyList();
+
+ //System.out.println("argument = " + argument);
+ return argument.getSamples(context);
+ }
+
+ @Override
+ @NotNull
+ public String getUsage() {
+ StringBuilder labelBuilder = new StringBuilder();
+
+ this.arguments.forEach(argument -> {
+ if (!labelBuilder.isEmpty()) {
+ labelBuilder.append(" ");
+ }
+ labelBuilder.append(argument.getLocalized());
+ });
+
+ StringBuilder flagBuilder = new StringBuilder();
+ this.flags.values().forEach(commandFlag -> {
+ if (!flagBuilder.isEmpty()) {
+ flagBuilder.append(" ");
+ }
+ flagBuilder.append(commandFlag.getPrefixedFormatted());
+ });
+
+ if (!flagBuilder.isEmpty()) {
+ labelBuilder.append(" ").append(flagBuilder);
+ }
+
+ return labelBuilder.toString();
+ }
+
+ @NotNull
+ public List> getArguments() {
+ return arguments;
+ }
+
+ @Nullable
+ public CommandFlag getFlag(@NotNull String name) {
+ return this.flags.get(name.toLowerCase());
+ }
+
+ @NotNull
+ public Collection getFlags() {
+ return this.flags.values();
+ }
+}
diff --git a/src/main/java/su/nightexpress/nightcore/command/experimental/node/NodeExecutor.java b/src/main/java/su/nightexpress/nightcore/command/experimental/node/NodeExecutor.java
new file mode 100644
index 0000000..c1919fb
--- /dev/null
+++ b/src/main/java/su/nightexpress/nightcore/command/experimental/node/NodeExecutor.java
@@ -0,0 +1,9 @@
+package su.nightexpress.nightcore.command.experimental.node;
+
+import org.jetbrains.annotations.NotNull;
+import su.nightexpress.nightcore.command.experimental.CommandContext;
+
+public interface NodeExecutor {
+
+ boolean run(@NotNull CommandContext context);
+}
diff --git a/src/main/java/su/nightexpress/nightcore/command/impl/WrappedCommand.java b/src/main/java/su/nightexpress/nightcore/command/impl/WrappedCommand.java
index fdebde0..73bc77a 100644
--- a/src/main/java/su/nightexpress/nightcore/command/impl/WrappedCommand.java
+++ b/src/main/java/su/nightexpress/nightcore/command/impl/WrappedCommand.java
@@ -4,6 +4,7 @@
import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.NotNull;
import su.nightexpress.nightcore.command.api.NightPluginCommand;
+import su.nightexpress.nightcore.util.text.NightMessage;
import java.util.Arrays;
import java.util.Collections;
@@ -26,7 +27,21 @@ public WrappedCommand(@NotNull Plugin plugin,
@NotNull String[] aliases,
@NotNull String description,
@NotNull String usage) {
- super(aliases[0], description, usage, Arrays.asList(aliases));
+ /*super(aliases[0], description, usage, Arrays.asList(aliases));
+ this.plugin = plugin;
+ this.executor = executor;
+ this.tabCompleter = tabCompleter;*/
+ this(plugin, executor, tabCompleter, aliases[0], aliases, description, usage);
+ }
+
+ public WrappedCommand(@NotNull Plugin plugin,
+ @NotNull CommandExecutor executor,
+ @NotNull TabCompleter tabCompleter,
+ @NotNull String name,
+ @NotNull String[] aliases,
+ @NotNull String description,
+ @NotNull String usage) {
+ super(name, NightMessage.clean(description), NightMessage.clean(usage), Arrays.asList(aliases));
this.plugin = plugin;
this.executor = executor;
this.tabCompleter = tabCompleter;
diff --git a/src/main/java/su/nightexpress/nightcore/config/FileConfig.java b/src/main/java/su/nightexpress/nightcore/config/FileConfig.java
index 87f0771..25538bb 100644
--- a/src/main/java/su/nightexpress/nightcore/config/FileConfig.java
+++ b/src/main/java/su/nightexpress/nightcore/config/FileConfig.java
@@ -1,6 +1,8 @@
package su.nightexpress.nightcore.config;
-import org.bukkit.*;
+import org.bukkit.Color;
+import org.bukkit.Location;
+import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.YamlConfiguration;
@@ -13,7 +15,6 @@
import org.bukkit.inventory.meta.PotionMeta;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import su.nightexpress.nightcore.util.Version;
import su.nightexpress.nightcore.NightCorePlugin;
import su.nightexpress.nightcore.util.*;
import su.nightexpress.nightcore.util.text.NightMessage;
@@ -341,15 +342,7 @@ public ItemStack getItem(@NotNull String path) {
meta.setLore(NightMessage.asLegacy(Colorizer.apply(this.getStringList(path + "Lore"))));
for (String sKey : this.getSection(path + "Enchants")) {
- Enchantment enchantment;
- NamespacedKey key = NamespacedKey.minecraft(sKey.toLowerCase());
-
- if (Version.isAtLeast(Version.V1_19_R3)) {
- enchantment = Registry.ENCHANTMENT.get(key);
- }
- else {
- enchantment = Enchantment.getByKey(key);
- }
+ Enchantment enchantment = BukkitThing.getEnchantment(sKey);
if (enchantment == null) continue;
int eLvl = this.getInt(path + "Enchants." + sKey);
@@ -441,19 +434,19 @@ public ItemStack getItemEncoded(@NotNull String path) {
String compressed = this.getString(path);
if (compressed == null) return null;
- return ItemUtil.decompress(compressed);
+ return ItemNbt.decompress(compressed);
}
public void setItemEncoded(@NotNull String path, @Nullable ItemStack item) {
- this.set(path, item == null ? null : ItemUtil.compress(item));
+ this.set(path, item == null ? null : ItemNbt.compress(item));
}
@NotNull
public ItemStack[] getItemsEncoded(@NotNull String path) {
- return ItemUtil.decompress(this.getStringList(path));
+ return ItemNbt.decompress(this.getStringList(path));
}
public void setItemsEncoded(@NotNull String path, @NotNull List item) {
- this.set(path, ItemUtil.compress(item));
+ this.set(path, ItemNbt.compress(item));
}
}
diff --git a/src/main/java/su/nightexpress/nightcore/core/CoreLang.java b/src/main/java/su/nightexpress/nightcore/core/CoreLang.java
index 15f67e8..af26645 100644
--- a/src/main/java/su/nightexpress/nightcore/core/CoreLang.java
+++ b/src/main/java/su/nightexpress/nightcore/core/CoreLang.java
@@ -6,15 +6,37 @@
import su.nightexpress.nightcore.language.entry.LangItem;
import su.nightexpress.nightcore.language.entry.LangString;
import su.nightexpress.nightcore.language.entry.LangText;
-import su.nightexpress.nightcore.util.Placeholders;
import static su.nightexpress.nightcore.util.Placeholders.*;
import static su.nightexpress.nightcore.util.text.tag.Tags.*;
public class CoreLang {
+ public static final LangString COMMAND_ARGUMENT_FORMAT_REQUIRED = LangString.of("Command.Argument.Type.Required",
+ LIGHT_RED.enclose("<" + GENERIC_NAME + ">"));
+
+ public static final LangString COMMAND_ARGUMENT_FORMAT_OPTIONAL = LangString.of("Command.Argument.Type.Optional",
+ LIGHT_YELLOW.enclose("[" + GENERIC_NAME + "]"));
+
+ public static final LangString COMMAND_FLAG_FORMAT = LangString.of("Command.Flag.Format",
+ LIGHT_GRAY.enclose("[" + GENERIC_NAME + "]"));
+
+ public static final LangString COMMAND_ARGUMENT_NAME_GENERIC = LangString.of("Command.Argument.Name.Generic", "value");
+ public static final LangString COMMAND_ARGUMENT_NAME_TYPE = LangString.of("Command.Argument.Name.Type", "type");
+ public static final LangString COMMAND_ARGUMENT_NAME_NAME = LangString.of("Command.Argument.Name.Name", "name");
+ public static final LangString COMMAND_ARGUMENT_NAME_PLAYER = LangString.of("Command.Argument.Name.Player", "player");
+ public static final LangString COMMAND_ARGUMENT_NAME_WORLD = LangString.of("Command.Argument.Name.World", "world");
+ public static final LangString COMMAND_ARGUMENT_NAME_AMOUNT = LangString.of("Command.Argument.Name.Amount", "amount");
+ public static final LangString COMMAND_ARGUMENT_NAME_MATERIAL = LangString.of("Command.Argument.Name.Material", "material");
+ public static final LangString COMMAND_ARGUMENT_NAME_ITEM_MATERIAL = LangString.of("Command.Argument.Name.ItemMaterial", "item type");
+ public static final LangString COMMAND_ARGUMENT_NAME_BLOCK_MATERIAL = LangString.of("Command.Argument.Name.BlockMaterial", "block type");
+ public static final LangString COMMAND_ARGUMENT_NAME_ENCHANTMENT = LangString.of("Command.Argument.Name.Enchantment", "enchantment");
+ //public static final LangString COMMAND_ARGUMENT_NAME_POTION_EFFECT = LangString.of("Command.Argument.Name.Effect", "effect");
+ //public static final LangString COMMAND_ARGUMENT_NAME_ATTRIBUTE = LangString.of("Command.Argument.Name.Attribute", "attribute");
+
public static final LangText COMMAND_HELP_LIST = LangText.of("Command.Help.List",
TAG_NO_PREFIX,
+ " ",
" " + YELLOW.enclose(BOLD.enclose(GENERIC_NAME)) + GRAY.enclose(" - ") + YELLOW.enclose(BOLD.enclose("Commands:")),
" ",
GRAY.enclose(" " + RED.enclose(BOLD.enclose("<>")) + " - Required, " + GREEN.enclose(BOLD.enclose("[]")) + " - Optional."),
@@ -24,18 +46,16 @@ public class CoreLang {
);
public static final LangString COMMAND_HELP_ENTRY = LangString.of("Command.Help.Entry",
- " " + YELLOW.enclose( "/" + COMMAND_LABEL) + " " + ORANGE.enclose(Placeholders.COMMAND_USAGE) + GRAY.enclose(" - " + COMMAND_DESCRIPTION)
+ " " + YELLOW.enclose("/" + COMMAND_LABEL) + " " + ORANGE.enclose(COMMAND_USAGE) + GRAY.enclose(" - " + COMMAND_DESCRIPTION)
);
public static final LangString COMMAND_HELP_DESC = LangString.of("Command.Help.Desc", "Show help page.");
- public static final LangString COMMAND_CHECKPERM_DESC = LangString.of("Command.CheckPerm.Desc", "Print player permission info.");
- public static final LangString COMMAND_CHECKPERM_USAGE = LangString.of("Command.CheckPerm.Usage", "");
+ public static final LangString COMMAND_CHECKPERM_DESC = LangString.of("Command.CheckPerm.Desc", "Print player permission info.");
- public static final LangString COMMAND_RELOAD_DESC = LangString.of("Command.Reload.Desc",
- "Reload the plugin.");
+ public static final LangString COMMAND_RELOAD_DESC = LangString.of("Command.Reload.Desc", "Reload the plugin.");
- public static final LangText COMMAND_RELOAD_DONE = LangText.of("Command.Reload.Done",
+ public static final LangText COMMAND_RELOAD_DONE = LangText.of("Command.Reload.Done",
LIGHT_GRAY.enclose("Plugin " + LIGHT_GREEN.enclose("reloaded") + "!"));
public static final LangString TIME_DAY = LangString.of("Time.Day", GENERIC_AMOUNT + "d.");
@@ -55,16 +75,66 @@ public class CoreLang {
public static final LangString OTHER_UNLIMITED = LangString.of("Other.Unlimited", "Unlimited");
public static final LangString OTHER_INFINITY = LangString.of("Other.Infinity", "∞");
- public static final LangText ERROR_INVALID_PLAYER = LangText.of("Error.Invalid_Player", RED.enclose("Player not found."));
- public static final LangText ERROR_INVALID_WORLD = LangText.of("Error.Invalid_World", RED.enclose("Invalid world."));
- public static final LangText ERROR_INVALID_NUMBER = LangText.of("Error.Invalid_Number", RED.enclose(GENERIC_VALUE + " is not a valid number."));
- public static final LangText ERROR_NO_PERMISSION = LangText.of("Error.NoPermission", RED.enclose("You don't have permissions to do that!"));
- public static final LangText ERROR_COMMAND_NOT_YOURSELF = LangText.of("Error.Command.NotYourself", RED.enclose("This command can not be used on yourself."));
- public static final LangText ERROR_COMMAND_PLAYER_ONLY = LangText.of("Error.Command.PlayerOnly", RED.enclose("This command is for players only."));
- public static final LangText ERROR_COMMAND_USAGE = LangText.of("Error.Command.Usage",
+ public static final LangString ENTRY_GOOD = LangString.of("Entry.Good", GREEN.enclose("✔") + " " + GRAY.enclose(GENERIC_ENTRY));
+ public static final LangString ENTRY_BAD = LangString.of("Entry.Bad", RED.enclose("✘") + " " + GRAY.enclose(GENERIC_ENTRY));
+ public static final LangString ENTRY_WARN = LangString.of("Entry.Warn", ORANGE.enclose("[❗]") + " " + GRAY.enclose(GENERIC_ENTRY));
+
+ public static final LangText ERROR_INVALID_PLAYER = LangText.of("Error.Invalid_Player",
+ RED.enclose("Invalid player!"));
+
+ public static final LangText ERROR_INVALID_WORLD = LangText.of("Error.Invalid_World",
+ RED.enclose("Invalid world!"));
+
+ public static final LangText ERROR_INVALID_NUMBER = LangText.of("Error.Invalid_Number",
+ RED.enclose("Invalid number!"));
+
+ public static final LangText ERROR_INVALID_MATERIAL = LangText.of("Error.InvalidMaterial",
+ RED.enclose("Invalid material!"));
+
+ public static final LangText ERROR_INVALID_ENCHANTMENT = LangText.of("Error.InvalidEnchantment",
+ RED.enclose("Invalid enchantment!"));
+
+ /*public static final LangText ERROR_INVALID_POTION_EFFECT = LangText.of("Error.InvalidPotionEffectType",
+ LIGHT_GRAY.enclose(LIGHT_RED.enclose(GENERIC_VALUE) + " is not a valid potion effect type!"));
+
+ public static final LangText ERROR_INVALID_ATTRIBUTE = LangText.of("Error.InvalidAttribute",
+ LIGHT_GRAY.enclose(LIGHT_RED.enclose(GENERIC_VALUE) + " is not a valid attribute!"));*/
+
+ public static final LangText ERROR_NO_PERMISSION = LangText.of("Error.NoPermission",
+ RED.enclose("You don't have permissions to do that!"));
+
+ public static final LangText ERROR_COMMAND_PARSE_FLAG = LangText.of("Error.Command.ParseFlag",
+ LIGHT_GRAY.enclose("Invalid value " + LIGHT_RED.enclose(GENERIC_VALUE) + " for " + LIGHT_RED.enclose(GENERIC_NAME) + " flag."));
+
+ public static final LangText ERROR_COMMAND_PARSE_ARGUMENT = LangText.of("Error.Command.ParseArgument",
+ LIGHT_GRAY.enclose("Invalid value " + LIGHT_RED.enclose(GENERIC_VALUE) + " for " + LIGHT_RED.enclose(GENERIC_NAME) + " argument."));
+
+ public static final LangText ERROR_COMMAND_INVALID_PLAYER_ARGUMENT = LangText.of("Error.Command.Argument.InvalidPlayer",
+ LIGHT_GRAY.enclose(LIGHT_RED.enclose("Can not find player " + GENERIC_VALUE) + "!"));
+
+ public static final LangText ERROR_COMMAND_INVALID_WORLD_ARGUMENT = LangText.of("Error.Command.Argument.InvalidWorld",
+ LIGHT_GRAY.enclose(LIGHT_RED.enclose("Can not find world " + GENERIC_VALUE) + "!"));
+
+ public static final LangText ERROR_COMMAND_INVALID_NUMBER_ARGUMENT = LangText.of("Error.Command.Argument.InvalidNumber",
+ LIGHT_GRAY.enclose(LIGHT_RED.enclose(GENERIC_VALUE) + " is not a valid number!"));
+
+ public static final LangText ERROR_COMMAND_INVALID_MATERIAL_ARGUMENT = LangText.of("Error.Command.Argument.InvalidMaterial",
+ LIGHT_GRAY.enclose(LIGHT_RED.enclose(GENERIC_VALUE) + " is not a valid material!"));
+
+ public static final LangText ERROR_COMMAND_INVALID_ENCHANTMENT_ARGUMENT = LangText.of("Error.Command.Argument.InvalidEnchantment",
+ LIGHT_GRAY.enclose(LIGHT_RED.enclose(GENERIC_VALUE) + " is not a valid enchantment!"));
+
+ public static final LangText ERROR_COMMAND_NOT_YOURSELF = LangText.of("Error.Command.NotYourself",
+ RED.enclose("This command can not be used on yourself."));
+
+ public static final LangText ERROR_COMMAND_PLAYER_ONLY = LangText.of("Error.Command.PlayerOnly",
+ RED.enclose("This command is for players only."));
+
+ public static final LangText ERROR_COMMAND_USAGE = LangText.of("Error.Command.Usage",
TAG_NO_PREFIX,
+ " ",
RED.enclose("Error: ") + GRAY.enclose("Wrong arguments!"),
- RED.enclose("Usage: ") + YELLOW.enclose("/" + Placeholders.COMMAND_LABEL) + " " + ORANGE.enclose(Placeholders.COMMAND_USAGE),
+ RED.enclose("Usage: ") + YELLOW.enclose("/" + COMMAND_LABEL) + " " + ORANGE.enclose(COMMAND_USAGE),
" "
);
@@ -85,10 +155,10 @@ public class CoreLang {
public static final LangString EDITOR_INPUT_ERROR_NOT_INTEGER = LangString.of("Editor.Input.Error.NotInteger", GRAY.enclose("Expecting " + RED.enclose("whole") + " number!"));
public static final LangString EDITOR_INPUT_ERROR_GENERIC = LangString.of("Editor.Input.Error.Generic", GRAY.enclose("Invalid value!"));
- public static final LangItem EDITOR_ITEM_CLOSE = LangItem.of("Editor.Generic.Close", RED.enclose("(✕) Exit"));
- public static final LangItem EDITOR_ITEM_RETURN = LangItem.of("Editor.Generic.Return", GRAY.enclose("(↓) ") + WHITE.enclose("Return"));
- public static final LangItem EDITOR_ITEM_NEXT_PAGE = LangItem.of("Editor.Generic.NextPage", WHITE.enclose("Next Page") + GRAY.enclose(" (→)"));
- public static final LangItem EDITOR_ITEM_PREVIOUS_PAGE = LangItem.of("Editor.Generic.PreviousPage", GRAY.enclose("(←) ") + WHITE.enclose("Previous Page"));
+ public static final LangItem EDITOR_ITEM_CLOSE = LangItem.of("Editor.Generic.Close", LIGHT_RED.enclose(BOLD.enclose("Exit")));
+ public static final LangItem EDITOR_ITEM_RETURN = LangItem.of("Editor.Generic.Return", LIGHT_GRAY.enclose(BOLD.enclose("Return")));
+ public static final LangItem EDITOR_ITEM_NEXT_PAGE = LangItem.of("Editor.Generic.NextPage", LIGHT_GRAY.enclose("Next Page →"));
+ public static final LangItem EDITOR_ITEM_PREVIOUS_PAGE = LangItem.of("Editor.Generic.PreviousPage", LIGHT_GRAY.enclose("← Previous Page"));
public static final LangString NUMBER_SHORT_THOUSAND = LangString.of("Number.Thousand", "k");
public static final LangString NUMBER_SHORT_MILLION = LangString.of("Number.Million", "m");
@@ -105,4 +175,19 @@ public static String getYesOrNo(boolean value) {
public static String getEnabledOrDisabled(boolean value) {
return (value ? OTHER_ENABLED : OTHER_DISABLED).getString();
}
+
+ @NotNull
+ public static String goodEntry(@NotNull String str) {
+ return ENTRY_GOOD.getString().replace(GENERIC_ENTRY, str);
+ }
+
+ @NotNull
+ public static String badEntry(@NotNull String str) {
+ return ENTRY_BAD.getString().replace(GENERIC_ENTRY, str);
+ }
+
+ @NotNull
+ public static String warnEntry(@NotNull String str) {
+ return ENTRY_WARN.getString().replace(GENERIC_ENTRY, str);
+ }
}
diff --git a/src/main/java/su/nightexpress/nightcore/core/command/CheckPermCommand.java b/src/main/java/su/nightexpress/nightcore/core/command/CheckPermCommand.java
index c8f7700..ea724ea 100644
--- a/src/main/java/su/nightexpress/nightcore/core/command/CheckPermCommand.java
+++ b/src/main/java/su/nightexpress/nightcore/core/command/CheckPermCommand.java
@@ -1,58 +1,43 @@
package su.nightexpress.nightcore.core.command;
-import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import su.nightexpress.nightcore.NightCore;
-import su.nightexpress.nightcore.command.CommandResult;
-import su.nightexpress.nightcore.command.impl.AbstractCommand;
+import su.nightexpress.nightcore.command.experimental.CommandContext;
+import su.nightexpress.nightcore.command.experimental.argument.ArgumentTypes;
+import su.nightexpress.nightcore.command.experimental.argument.ParsedArguments;
+import su.nightexpress.nightcore.command.experimental.node.ChainedNode;
+import su.nightexpress.nightcore.command.experimental.node.DirectNode;
import su.nightexpress.nightcore.core.CoreLang;
import su.nightexpress.nightcore.core.CorePerms;
import su.nightexpress.nightcore.integration.VaultHook;
import su.nightexpress.nightcore.util.Colorizer;
-import su.nightexpress.nightcore.util.Players;
import su.nightexpress.nightcore.util.text.NightMessage;
-import java.util.List;
-
import static su.nightexpress.nightcore.util.text.tag.Tags.*;
-public class CheckPermCommand extends AbstractCommand {
+public class CheckPermCommand {
- public CheckPermCommand(@NotNull NightCore plugin) {
- super(plugin, new String[]{"checkperm"}, CorePerms.COMMAND_CHECK_PERM);
- this.setDescription(CoreLang.COMMAND_CHECKPERM_DESC);
- this.setUsage(CoreLang.COMMAND_CHECKPERM_USAGE);
- }
+ private static final String ARG_PLAYER = "player";
- @Override
- @NotNull
- public List getTab(@NotNull Player player, int arg, @NotNull String[] args) {
- if (arg == 1) {
- return Players.playerNames(player);
- }
- return super.getTab(player, arg, args);
+ public static void inject(@NotNull NightCore plugin, @NotNull ChainedNode node) {
+ node.addChildren(DirectNode.builder(plugin, "checkperm")
+ .permission(CorePerms.COMMAND_CHECK_PERM)
+ .description(CoreLang.COMMAND_CHECKPERM_DESC)
+ .withArgument(ArgumentTypes.player(ARG_PLAYER).required())
+ .executes(CheckPermCommand::execute)
+ );
}
- @Override
- protected void onExecute(@NotNull CommandSender sender, @NotNull CommandResult result) {
- if (result.length() < 2) {
- this.errorUsage(sender);
- return;
- }
-
- Player player = Players.getPlayer(result.getArg(1));
- if (player == null) {
- this.errorPlayer(sender);
- return;
- }
-
+ public static boolean execute(@NotNull CommandContext context, @NotNull ParsedArguments arguments) {
+ Player player = arguments.getPlayerArgument(ARG_PLAYER);
String builder =
BOLD.enclose(LIGHT_YELLOW.enclose("Permissions report for ") + LIGHT_ORANGE.enclose(player.getName() + ":")) +
- LIGHT_ORANGE.enclose("▪ " + LIGHT_YELLOW.enclose("Primary Group: ") + Colorizer.plain(VaultHook.getPermissionGroup(player))) +
- LIGHT_ORANGE.enclose("▪ " + LIGHT_YELLOW.enclose("All Groups: ") + Colorizer.plain(String.join(", ", VaultHook.getPermissionGroups(player)))) +
- LIGHT_ORANGE.enclose("▪ " + LIGHT_YELLOW.enclose("Prefix: ") + VaultHook.getPrefix(player)) +
- LIGHT_ORANGE.enclose("▪ " + LIGHT_YELLOW.enclose("Suffix: ") + VaultHook.getSuffix(player));
- NightMessage.create(builder).send(sender);
+ LIGHT_ORANGE.enclose("▪ " + LIGHT_YELLOW.enclose("Primary Group: ") + Colorizer.plain(VaultHook.getPermissionGroup(player))) +
+ LIGHT_ORANGE.enclose("▪ " + LIGHT_YELLOW.enclose("All Groups: ") + Colorizer.plain(String.join(", ", VaultHook.getPermissionGroups(player)))) +
+ LIGHT_ORANGE.enclose("▪ " + LIGHT_YELLOW.enclose("Prefix: ") + VaultHook.getPrefix(player)) +
+ LIGHT_ORANGE.enclose("▪ " + LIGHT_YELLOW.enclose("Suffix: ") + VaultHook.getSuffix(player));
+ NightMessage.create(builder).send(context.getSender());
+ return true;
}
}
diff --git a/src/main/java/su/nightexpress/nightcore/core/listener/CoreListener.java b/src/main/java/su/nightexpress/nightcore/core/listener/CoreListener.java
index f2eed84..0b40795 100644
--- a/src/main/java/su/nightexpress/nightcore/core/listener/CoreListener.java
+++ b/src/main/java/su/nightexpress/nightcore/core/listener/CoreListener.java
@@ -17,8 +17,10 @@ public CoreListener(@NotNull NightCore plugin) {
@EventHandler(priority = EventPriority.NORMAL)
public void onServiceRegisterEvent(ServiceRegisterEvent event) {
- if (!Plugins.hasVault()) return;
+ //if (!Plugins.hasVault()) return;
- VaultHook.onServiceRegisterEvent(event);
+ if (Plugins.isLoaded(Plugins.VAULT)) {
+ VaultHook.onServiceRegisterEvent(event);
+ }
}
}
diff --git a/src/main/java/su/nightexpress/nightcore/database/DatabaseConfig.java b/src/main/java/su/nightexpress/nightcore/database/DatabaseConfig.java
index f513781..5073026 100644
--- a/src/main/java/su/nightexpress/nightcore/database/DatabaseConfig.java
+++ b/src/main/java/su/nightexpress/nightcore/database/DatabaseConfig.java
@@ -59,7 +59,13 @@ public DatabaseConfig(
@NotNull
public static DatabaseConfig read(@NotNull NightCorePlugin plugin) {
- FileConfig cfg = plugin.getConfig();
+ String defPrefix = StringUtil.lowerCaseUnderscore(plugin.getName());
+ return read(plugin.getConfig(), defPrefix);
+ }
+
+ @NotNull
+ public static DatabaseConfig read(@NotNull FileConfig cfg, @NotNull String defaultPrefix) {
+ //FileConfig cfg = plugin.getConfig();
String path = "Database.";
DatabaseType databaseType = ConfigValue.create(path + "Type", DatabaseType.class, DatabaseType.SQLITE,
@@ -78,7 +84,7 @@ public static DatabaseConfig read(@NotNull NightCorePlugin plugin) {
"Set to '-1' to disable.")
.read(cfg);
- String tablePrefix = ConfigValue.create(path + "Table_Prefix", StringUtil.lowerCaseUnderscore(plugin.getName()),
+ String tablePrefix = ConfigValue.create(path + "Table_Prefix", defaultPrefix,
"Custom prefix for plugin tables in database.")
.read(cfg);
diff --git a/src/main/java/su/nightexpress/nightcore/database/serialize/ItemStackSerializer.java b/src/main/java/su/nightexpress/nightcore/database/serialize/ItemStackSerializer.java
index 8d91f9a..c514967 100644
--- a/src/main/java/su/nightexpress/nightcore/database/serialize/ItemStackSerializer.java
+++ b/src/main/java/su/nightexpress/nightcore/database/serialize/ItemStackSerializer.java
@@ -2,7 +2,7 @@
import com.google.gson.*;
import org.bukkit.inventory.ItemStack;
-import su.nightexpress.nightcore.util.ItemUtil;
+import su.nightexpress.nightcore.util.ItemNbt;
import java.lang.reflect.Type;
@@ -11,14 +11,14 @@ public class ItemStackSerializer implements JsonSerializer, JsonDeser
@Override
public JsonElement serialize(ItemStack item, Type type, JsonSerializationContext context) {
JsonObject object = new JsonObject();
- object.addProperty("data64", ItemUtil.compress(item));
+ object.addProperty("data64", ItemNbt.compress(item));
return object;
}
@Override
public ItemStack deserialize(JsonElement json, Type type, JsonDeserializationContext context) throws JsonParseException {
JsonObject object = json.getAsJsonObject();
- return ItemUtil.decompress(object.get("data64").getAsString());
+ return ItemNbt.decompress(object.get("data64").getAsString());
}
}
diff --git a/src/main/java/su/nightexpress/nightcore/dialog/DialogListener.java b/src/main/java/su/nightexpress/nightcore/dialog/DialogListener.java
index a719d61..c0770c7 100644
--- a/src/main/java/su/nightexpress/nightcore/dialog/DialogListener.java
+++ b/src/main/java/su/nightexpress/nightcore/dialog/DialogListener.java
@@ -16,6 +16,8 @@
public class DialogListener extends AbstractListener {
+ // TODO Timeout
+
public DialogListener(@NotNull NightCore plugin) {
super(plugin);
}
diff --git a/src/main/java/su/nightexpress/nightcore/language/LangAssets.java b/src/main/java/su/nightexpress/nightcore/language/LangAssets.java
index 04fa83b..c03755c 100644
--- a/src/main/java/su/nightexpress/nightcore/language/LangAssets.java
+++ b/src/main/java/su/nightexpress/nightcore/language/LangAssets.java
@@ -92,7 +92,7 @@ public static String get(@NotNull Enchantment enchantment) {
@NotNull
public static String getAsset(@NotNull String path, @NotNull Keyed keyed) {
- return getAsset(path, keyed.getKey().getKey());
+ return getAsset(path, BukkitThing.toString(keyed));
}
@NotNull
@@ -107,7 +107,7 @@ public static Optional getAsset(@NotNull String path) {
@NotNull
public static String getOrCreate(@NotNull String path, @NotNull Keyed keyed) {
- return getOrCreate(path, keyed.getKey().getKey());
+ return getOrCreate(path, BukkitThing.toString(keyed));
}
@NotNull
diff --git a/src/main/java/su/nightexpress/nightcore/language/LangManager.java b/src/main/java/su/nightexpress/nightcore/language/LangManager.java
index 9952183..44c7543 100644
--- a/src/main/java/su/nightexpress/nightcore/language/LangManager.java
+++ b/src/main/java/su/nightexpress/nightcore/language/LangManager.java
@@ -4,6 +4,7 @@
import su.nightexpress.nightcore.NightCorePlugin;
import su.nightexpress.nightcore.config.FileConfig;
import su.nightexpress.nightcore.language.entry.LangEntry;
+import su.nightexpress.nightcore.language.entry.LangEnum;
import su.nightexpress.nightcore.manager.SimpleManager;
import su.nightexpress.nightcore.util.Plugins;
import su.nightexpress.nightcore.util.Reflex;
@@ -57,36 +58,18 @@ private String validateConfig(@NotNull String langCode) {
return DEFAULT_LANGUAGE;
}
return langCode;
-
- /*if (file.exists()) return langCode;
-
- try {
- InputStream input = plugin.getClass().getResourceAsStream(DIR_LANG + fileName);
- if (input != null) {
- FileUtil.create(file);
- FileUtil.copy(input, file);
- return langCode;
- }
- return isDefault(langCode) ? langCode : this.extractConfig(DEFAULT_LANGUAGE);
- }
- catch (Exception exception) {
- exception.printStackTrace();
- return isDefault(langCode) ? langCode : this.extractConfig(DEFAULT_LANGUAGE);
- }*/
}
public void loadEntries(@NotNull Class> clazz) {
Reflex.getFields(clazz, LangEntry.class).forEach(entry -> {
entry.load(this.plugin);
});
- }
-
- /*public void loadEditor(@NotNull Class> clazz) {
- Reflex.getFields(clazz, LangItem.class).forEach(entry -> {
- entry.load(this.plugin);
+ Reflex.getFields(clazz, LangEnum.class).forEach(langEnum -> {
+ langEnum.load(this.plugin);
});
- }*/
+ }
+ @Deprecated
public void loadEnum(@NotNull Class extends Enum>> clazz) {
for (Object eName : clazz.getEnumConstants()) {
String name = eName.toString();
@@ -97,6 +80,7 @@ public void loadEnum(@NotNull Class extends Enum>> clazz) {
}
@NotNull
+ @Deprecated
public String getEnum(@NotNull Enum> entry) {
String path = entry.getDeclaringClass().getSimpleName() + "." + entry.name();
String locEnum = this.config.getString(path);
diff --git a/src/main/java/su/nightexpress/nightcore/language/entry/LangEnum.java b/src/main/java/su/nightexpress/nightcore/language/entry/LangEnum.java
new file mode 100644
index 0000000..d1dd675
--- /dev/null
+++ b/src/main/java/su/nightexpress/nightcore/language/entry/LangEnum.java
@@ -0,0 +1,43 @@
+package su.nightexpress.nightcore.language.entry;
+
+import org.jetbrains.annotations.NotNull;
+import su.nightexpress.nightcore.NightCorePlugin;
+import su.nightexpress.nightcore.config.ConfigValue;
+import su.nightexpress.nightcore.config.FileConfig;
+import su.nightexpress.nightcore.util.StringUtil;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.stream.Stream;
+
+public class LangEnum> {
+
+ private final String path;
+ private final Class clazz;
+ private final Map localeMap;
+
+ public LangEnum(@NotNull String path, @NotNull Class clazz) {
+ this.path = path;
+ this.clazz = clazz;
+ this.localeMap = new HashMap<>();
+ }
+
+ @NotNull
+ public static > LangEnum of(@NotNull String path, @NotNull Class clazz) {
+ return new LangEnum<>(path, clazz);
+ }
+
+ public void load(@NotNull NightCorePlugin plugin) {
+ FileConfig config = plugin.getLang();
+
+ Stream.of(this.clazz.getEnumConstants()).forEach(con -> {
+ String text = ConfigValue.create(this.path + "." + con.name(), StringUtil.capitalizeUnderscored(con.name())).read(config);
+ this.localeMap.put(con, text);
+ });
+ }
+
+ @NotNull
+ public String getLocalized(@NotNull E con) {
+ return this.localeMap.getOrDefault(con, con.name());
+ }
+}
diff --git a/src/main/java/su/nightexpress/nightcore/manager/AbstractListener.java b/src/main/java/su/nightexpress/nightcore/manager/AbstractListener.java
index a27a292..6e78047 100644
--- a/src/main/java/su/nightexpress/nightcore/manager/AbstractListener.java
+++ b/src/main/java/su/nightexpress/nightcore/manager/AbstractListener.java
@@ -3,7 +3,7 @@
import org.jetbrains.annotations.NotNull;
import su.nightexpress.nightcore.NightCorePlugin;
-public abstract class AbstractListener implements SimpeListener {
+public abstract class AbstractListener
implements SimpleListener {
@NotNull
public final P plugin;
diff --git a/src/main/java/su/nightexpress/nightcore/manager/AbstractManager.java b/src/main/java/su/nightexpress/nightcore/manager/AbstractManager.java
index 2c086ee..6ff23b2 100644
--- a/src/main/java/su/nightexpress/nightcore/manager/AbstractManager.java
+++ b/src/main/java/su/nightexpress/nightcore/manager/AbstractManager.java
@@ -11,8 +11,8 @@
public abstract class AbstractManager
extends SimpleManager
{
- protected final Set listeners;
- protected final List tasks;
+ protected final Set listeners;
+ protected final List tasks;
public AbstractManager(@NotNull P plugin) {
super(plugin);
@@ -24,12 +24,12 @@ public AbstractManager(@NotNull P plugin) {
public void shutdown() {
this.tasks.forEach(UniTask::stop);
this.tasks.clear();
- this.listeners.forEach(SimpeListener::unregisterListeners);
+ this.listeners.forEach(SimpleListener::unregisterListeners);
this.listeners.clear();
super.shutdown();
}
- protected void addListener(@NotNull SimpeListener listener) {
+ protected void addListener(@NotNull SimpleListener listener) {
if (this.listeners.add(listener)) {
listener.registerListeners();
}
diff --git a/src/main/java/su/nightexpress/nightcore/manager/SimpeListener.java b/src/main/java/su/nightexpress/nightcore/manager/SimpeListener.java
index 2ea13c4..20bdec6 100644
--- a/src/main/java/su/nightexpress/nightcore/manager/SimpeListener.java
+++ b/src/main/java/su/nightexpress/nightcore/manager/SimpeListener.java
@@ -3,6 +3,7 @@
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
+@Deprecated
public interface SimpeListener extends Listener {
void registerListeners();
diff --git a/src/main/java/su/nightexpress/nightcore/manager/SimpleListener.java b/src/main/java/su/nightexpress/nightcore/manager/SimpleListener.java
new file mode 100644
index 0000000..29c3f57
--- /dev/null
+++ b/src/main/java/su/nightexpress/nightcore/manager/SimpleListener.java
@@ -0,0 +1,13 @@
+package su.nightexpress.nightcore.manager;
+
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.Listener;
+
+public interface SimpleListener extends Listener {
+
+ void registerListeners();
+
+ default void unregisterListeners() {
+ HandlerList.unregisterAll(this);
+ }
+}
diff --git a/src/main/java/su/nightexpress/nightcore/menu/MenuListener.java b/src/main/java/su/nightexpress/nightcore/menu/MenuListener.java
index e918e68..d8a2c9a 100644
--- a/src/main/java/su/nightexpress/nightcore/menu/MenuListener.java
+++ b/src/main/java/su/nightexpress/nightcore/menu/MenuListener.java
@@ -48,7 +48,7 @@ public void onMenuItemClick(InventoryClickEvent event) {
int slot = event.getRawSlot();
boolean isMenu = slot < inventory.getSize();
- boolean isEmptyItem = item == null || item.getType().isAir();
+ //boolean isEmptyItem = item == null || item.getType().isAir();
ClickResult result = new ClickResult(slot, item, isMenu);
menu.onClick(viewer, result, event);
diff --git a/src/main/java/su/nightexpress/nightcore/menu/MenuOptions.java b/src/main/java/su/nightexpress/nightcore/menu/MenuOptions.java
index 398ad74..30241a2 100644
--- a/src/main/java/su/nightexpress/nightcore/menu/MenuOptions.java
+++ b/src/main/java/su/nightexpress/nightcore/menu/MenuOptions.java
@@ -10,17 +10,26 @@
public class MenuOptions {
- private String title;
- private int size;
+ private String title;
+ private int size;
private InventoryType type;
- private int autoRefresh;
+ private int autoRefresh;
private long lastAutoRefresh;
+ @Deprecated
public MenuOptions(@NotNull String title, int size, @NotNull InventoryType type) {
this(title, size, type, 0);
}
+ public MenuOptions(@NotNull String title, @NotNull MenuSize size) {
+ this(title, size.getSize(), InventoryType.CHEST, 0);
+ }
+
+ public MenuOptions(@NotNull String title, @NotNull InventoryType type) {
+ this(title, 27, type, 0);
+ }
+
public MenuOptions(@NotNull String title, int size, @NotNull InventoryType type, int autoRefresh) {
this.setTitle(title);
this.setSize(size);
@@ -30,6 +39,8 @@ public MenuOptions(@NotNull String title, int size, @NotNull InventoryType type,
public MenuOptions(@NotNull MenuOptions options) {
this(options.getTitle(), options.getSize(), options.getType(), options.getAutoRefresh());
+ this.size = options.getSize();
+ this.autoRefresh = options.getAutoRefresh();
this.lastAutoRefresh = 0L;
}
diff --git a/src/main/java/su/nightexpress/nightcore/menu/MenuSize.java b/src/main/java/su/nightexpress/nightcore/menu/MenuSize.java
new file mode 100644
index 0000000..af531b3
--- /dev/null
+++ b/src/main/java/su/nightexpress/nightcore/menu/MenuSize.java
@@ -0,0 +1,22 @@
+package su.nightexpress.nightcore.menu;
+
+public enum MenuSize {
+
+ CHEST_9(9),
+ CHEST_18(18),
+ CHEST_27(27),
+ CHEST_36(36),
+ CHEST_45(45),
+ CHEST_54(54)
+ ;
+
+ private final int size;
+
+ MenuSize(int size) {
+ this.size = size;
+ }
+
+ public int getSize() {
+ return size;
+ }
+}
diff --git a/src/main/java/su/nightexpress/nightcore/menu/MenuViewer.java b/src/main/java/su/nightexpress/nightcore/menu/MenuViewer.java
index 63580d8..d7575ba 100644
--- a/src/main/java/su/nightexpress/nightcore/menu/MenuViewer.java
+++ b/src/main/java/su/nightexpress/nightcore/menu/MenuViewer.java
@@ -11,11 +11,11 @@ public class MenuViewer {
private final Player player;
- private Inventory inventory;
+ private Inventory inventory;
private InventoryView view;
- private int page;
- private int pages;
- private long lastClickTime;
+ private int page;
+ private int pages;
+ private long lastClickTime;
public MenuViewer(@NotNull Player player) {
this.player = player;
diff --git a/src/main/java/su/nightexpress/nightcore/menu/impl/AbstractMenu.java b/src/main/java/su/nightexpress/nightcore/menu/impl/AbstractMenu.java
index dfc7af1..029b308 100644
--- a/src/main/java/su/nightexpress/nightcore/menu/impl/AbstractMenu.java
+++ b/src/main/java/su/nightexpress/nightcore/menu/impl/AbstractMenu.java
@@ -12,6 +12,7 @@
import su.nightexpress.nightcore.NightCorePlugin;
import su.nightexpress.nightcore.api.event.PlayerOpenMenuEvent;
import su.nightexpress.nightcore.dialog.Dialog;
+import su.nightexpress.nightcore.menu.MenuSize;
import su.nightexpress.nightcore.menu.api.Menu;
import su.nightexpress.nightcore.menu.link.Linked;
import su.nightexpress.nightcore.menu.MenuOptions;
@@ -35,6 +36,10 @@ public static void closeAll(@NotNull NightCorePlugin plugin) {
getActiveMenus().forEach(menu -> menu.close(plugin));
}
+ public static void clearAll(@NotNull NightCorePlugin plugin) {
+ getActiveMenus().stream().distinct().forEach(Menu::clear);
+ }
+
public static Collection