diff --git a/pom.xml b/pom.xml index 0a7f001..7cfa158 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ su.nightexpress.nightcore nightcore - 2.5.2.1 + 2.6.1 17 diff --git a/src/main/java/su/nightexpress/nightcore/NightCore.java b/src/main/java/su/nightexpress/nightcore/NightCore.java index 8d2feb8..2a964ed 100644 --- a/src/main/java/su/nightexpress/nightcore/NightCore.java +++ b/src/main/java/su/nightexpress/nightcore/NightCore.java @@ -1,9 +1,12 @@ package su.nightexpress.nightcore; import org.bukkit.Material; +import org.bukkit.enchantments.Enchantment; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import su.nightexpress.nightcore.command.base.ReloadSubCommand; +import su.nightexpress.nightcore.command.experimental.ImprovedCommands; +import su.nightexpress.nightcore.command.experimental.impl.ReloadCommand; +import su.nightexpress.nightcore.command.experimental.node.ChainedNode; import su.nightexpress.nightcore.config.PluginDetails; import su.nightexpress.nightcore.core.CoreConfig; import su.nightexpress.nightcore.core.CoreLang; @@ -13,16 +16,13 @@ import su.nightexpress.nightcore.dialog.Dialog; import su.nightexpress.nightcore.integration.VaultHook; import su.nightexpress.nightcore.language.LangAssets; -import su.nightexpress.nightcore.util.EntityUtil; -import su.nightexpress.nightcore.util.ItemUtil; -import su.nightexpress.nightcore.util.Plugins; -import su.nightexpress.nightcore.util.Version; +import su.nightexpress.nightcore.util.*; import su.nightexpress.nightcore.util.blocktracker.PlayerBlockTracker; import java.util.HashSet; import java.util.Set; -public class NightCore extends NightPlugin { +public class NightCore extends NightPlugin implements ImprovedCommands { private final Set childrens; private final CoreManager coreManager; @@ -36,11 +36,13 @@ public NightCore() { public void enable() { LangAssets.load(); + ChainedNode rootNode = this.getRootNode(); + if (Plugins.hasVault()) { VaultHook.setup(); - this.getBaseCommand().addChildren(new CheckPermCommand(this)); + CheckPermCommand.inject(this, rootNode); } - this.getBaseCommand().addChildren(new ReloadSubCommand(this, CorePerms.COMMAND_RELOAD)); + ReloadCommand.inject(this, rootNode, CorePerms.COMMAND_RELOAD); this.testMethods(); this.coreManager.setup(); @@ -78,18 +80,35 @@ public Set getChildrens() { private void testMethods() { if (Version.getCurrent() == Version.UNKNOWN) { - this.warn("Server Version: UNSUPPORTED (!)"); + this.warn("Server Version: UNSUPPORTED ✘"); } - else this.info("Server Version: " + Version.getCurrent().getLocalized() + " (OK)"); + else this.info("Server Version: " + Version.getCurrent().getLocalized() + " ✔"); - if (EntityUtil.ENTITY_COUNTER == null) { - this.warn("Entity Id Counter: NULL!"); + if (EntityUtil.setupEntityCounter(this)) { + this.info("Entity Id Counter: OK ✔"); } - else this.info("Entity Id Counter: OK."); + else this.error("Entity Id Counter: FAIL ✘"); - if (ItemUtil.compress(new ItemStack(Material.DIAMOND_SWORD)) == null) { - this.warn("Item NBT Compress: FAILED!"); + if (this.testItemNbt()) { + this.info("Item NBT Compress: OK ✔"); } - else this.info("Item NBT Compress: OK."); + else this.error("Item NBT Compress: FAIL ✘"); + } + + private boolean testItemNbt() { + if (!ItemNbt.setup(this)) return false; + + ItemStack testItem = new ItemStack(Material.DIAMOND_SWORD); + ItemUtil.editMeta(testItem, meta -> { + meta.setDisplayName("Test Item"); + meta.setLore(Lists.newList("Test Lore 1", "Test Lore 2", "Test Lore 3")); + meta.addEnchant(Enchantment.FIRE_ASPECT, 10, true); + }); + + String nbt = ItemNbt.compress(testItem); + if (nbt == null) return false; + + ItemStack decompressed = ItemNbt.decompress(nbt); + return decompressed != null && decompressed.getType() == testItem.getType(); } } diff --git a/src/main/java/su/nightexpress/nightcore/NightCorePlugin.java b/src/main/java/su/nightexpress/nightcore/NightCorePlugin.java index c1bb2c6..fa86b03 100644 --- a/src/main/java/su/nightexpress/nightcore/NightCorePlugin.java +++ b/src/main/java/su/nightexpress/nightcore/NightCorePlugin.java @@ -5,9 +5,9 @@ import org.bukkit.scheduler.BukkitScheduler; import org.bukkit.scheduler.BukkitTask; import org.jetbrains.annotations.NotNull; +import su.nightexpress.nightcore.command.CommandManager; import su.nightexpress.nightcore.command.api.NightPluginCommand; import su.nightexpress.nightcore.config.FileConfig; -import su.nightexpress.nightcore.command.CommandManager; import su.nightexpress.nightcore.config.PluginDetails; import su.nightexpress.nightcore.language.LangManager; import su.nightexpress.nightcore.util.wrapper.UniTask; @@ -24,7 +24,7 @@ public interface NightCorePlugin extends Plugin { void reload(); - @NotNull NightPluginCommand getBaseCommand(); + NightPluginCommand getBaseCommand(); @Override @NotNull FileConfig getConfig(); diff --git a/src/main/java/su/nightexpress/nightcore/NightPlugin.java b/src/main/java/su/nightexpress/nightcore/NightPlugin.java index 87fb18f..b4ca793 100644 --- a/src/main/java/su/nightexpress/nightcore/NightPlugin.java +++ b/src/main/java/su/nightexpress/nightcore/NightPlugin.java @@ -42,6 +42,7 @@ public void onEnable() { this.warn("=".repeat(35)); this.warn("WARNING: You're running an unsupported server version!"); this.warn("Expect bugs and broken features."); + this.warn("! NO DISCORD SUPPORT WILL BE GIVEN !"); this.warn("=".repeat(35)); } else if (version.isDeprecated()) { @@ -157,7 +158,7 @@ protected void unloadManagers() { this.disable(); - AbstractMenu.closeAll(this); // Close all GUIs. + AbstractMenu.clearAll(this); // Close all GUIs. HandlerList.unregisterAll(this); // Unregister all plugin listeners. this.getCommandManager().shutdown(); diff --git a/src/main/java/su/nightexpress/nightcore/command/CommandManager.java b/src/main/java/su/nightexpress/nightcore/command/CommandManager.java index 981c81f..2a4ea82 100644 --- a/src/main/java/su/nightexpress/nightcore/command/CommandManager.java +++ b/src/main/java/su/nightexpress/nightcore/command/CommandManager.java @@ -2,26 +2,33 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import su.nightexpress.nightcore.NightCorePlugin; +import su.nightexpress.nightcore.NightPlugin; import su.nightexpress.nightcore.command.api.NightPluginCommand; -import su.nightexpress.nightcore.manager.SimpleManager; import su.nightexpress.nightcore.command.base.HelpSubCommand; +import su.nightexpress.nightcore.command.experimental.ImprovedCommands; +import su.nightexpress.nightcore.command.experimental.RootCommand; +import su.nightexpress.nightcore.command.experimental.ServerCommand; +import su.nightexpress.nightcore.command.experimental.node.ChainedNode; import su.nightexpress.nightcore.command.impl.BaseCommand; +import su.nightexpress.nightcore.manager.SimpleManager; import su.nightexpress.nightcore.util.CommandUtil; import su.nightexpress.nightcore.util.Lists; import java.util.HashSet; import java.util.Set; -public class CommandManager extends SimpleManager { +public class CommandManager extends SimpleManager { private final Set commands; + private final Set serverCommands; - private BaseCommand mainCommand; + private BaseCommand mainCommand; + private RootCommand rootCommand; - public CommandManager(@NotNull NightCorePlugin plugin) { + public CommandManager(@NotNull NightPlugin plugin) { super(plugin); this.commands = new HashSet<>(); + this.serverCommands = new HashSet<>(); } @Override @@ -32,16 +39,28 @@ public void onLoad() { return; } - // Create main plugin command and attach help sub-command as a default executor. - this.mainCommand = new BaseCommand(this.plugin); - this.mainCommand.addDefaultCommand(new HelpSubCommand(this.plugin)); + if (this.plugin instanceof ImprovedCommands) { + this.rootCommand = RootCommand.chained(this.plugin, aliases, builder -> builder + // TODO Permission? + .localized(this.plugin.getNameLocalized()) + ); + this.registerCommand(this.rootCommand); + } + else { + // Create main plugin command and attach help sub-command as a default executor. + this.mainCommand = new BaseCommand(this.plugin); + this.mainCommand.addDefaultCommand(new HelpSubCommand(this.plugin)); - // Register main command as a bukkit command. - this.registerCommand(this.mainCommand); + // Register main command as a bukkit command. + this.registerCommand(this.mainCommand); + } } @Override public void onShutdown() { + this.serverCommands.forEach(ServerCommand::unregister); + this.serverCommands.clear(); + for (NightPluginCommand command : new HashSet<>(this.getCommands())) { this.unregisterCommand(command); command.getChildrens().clear(); @@ -54,11 +73,21 @@ public Set getCommands() { return this.commands; } + @NotNull + public Set getServerCommands() { + return serverCommands; + } + @NotNull public BaseCommand getMainCommand() { return this.mainCommand; } + @NotNull + public RootCommand 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> clazz) { for (Object eName : clazz.getEnumConstants()) { String name = eName.toString(); @@ -97,6 +80,7 @@ public void loadEnum(@NotNull Class> 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

getActiveMenus() { return new HashSet<>(PLAYER_MENUS.values()); } @@ -57,13 +62,18 @@ public AbstractMenu(@NotNull P plugin) { } public AbstractMenu(@NotNull P plugin, @NotNull String title, @NotNull InventoryType type) { - this(plugin, new MenuOptions(title, 27, type)); + this(plugin, new MenuOptions(title, type)); } + @Deprecated public AbstractMenu(@NotNull P plugin, @NotNull String title, int size) { this(plugin, new MenuOptions(title, size, InventoryType.CHEST)); } + public AbstractMenu(@NotNull P plugin, @NotNull String title, @NotNull MenuSize size) { + this(plugin, new MenuOptions(title, size)); + } + public AbstractMenu(@NotNull P plugin, @NotNull MenuOptions options) { this.plugin = plugin; this.id = UUID.randomUUID(); @@ -138,11 +148,15 @@ public boolean open(@NotNull MenuViewer viewer) { @Override public boolean open(@NotNull Player player) { - if (!this.canOpen(player)) return false; + if (!this.canOpen(player)) { + this.purgeViewer(player); + return false; + } PlayerOpenMenuEvent event = new PlayerOpenMenuEvent(player, this); this.plugin.getPluginManager().callEvent(event); if (event.isCancelled()) { + this.purgeViewer(player); //this.close(player); return false; } @@ -163,10 +177,12 @@ public boolean open(@NotNull Player player) { Inventory inventory = viewer.getInventory(); if (inventory == null) { this.plugin.debug("Could not create " + this.getClass().getSimpleName() + " menu for '" + player.getName() + "'."); + this.purgeViewer(player); return false; } if (inventory.getType() == InventoryType.CRAFTING) { this.plugin.warn("Got CRAFTING inventory when trying to open " + this.getClass().getSimpleName() + " menu for '" + player.getName() + "'."); + this.purgeViewer(player); return false; } @@ -213,22 +229,29 @@ public void onClose(@NotNull MenuViewer viewer, @NotNull InventoryCloseEvent eve } public void onClose(@NotNull Player player) { - MenuViewer viewer = this.viewers.remove(player.getUniqueId()); - if (viewer != null) { - this.getItems().removeIf(menuItem -> menuItem.getOptions().canBeDestroyed(viewer)); - } - PLAYER_MENUS.remove(player.getUniqueId()); + MenuViewer viewer = this.purgeViewer(player); // Do not clear link if entered Editor, so it can reopen menu without data loss when done. - if (viewer != null && this instanceof Linked linked && !Dialog.contains(player)) { + if (viewer != null && this instanceof Linked linked && linked.cleanOnClose() && !Dialog.contains(player)) { linked.getLink().clear(viewer); } + PLAYER_MENUS.remove(player.getUniqueId()); + if (this.getViewers().isEmpty() && !this.isPersistent()) { this.clear(); } } + @Nullable + private MenuViewer purgeViewer(@NotNull Player player) { + MenuViewer viewer = this.viewers.remove(player.getUniqueId()); + if (viewer != null) { + this.getItems().removeIf(menuItem -> menuItem.getOptions().canBeDestroyed(viewer)); + } + return viewer; + } + @Override public boolean isPersistent() { return true; diff --git a/src/main/java/su/nightexpress/nightcore/menu/impl/ConfigMenu.java b/src/main/java/su/nightexpress/nightcore/menu/impl/ConfigMenu.java index 81c8606..b03e62c 100644 --- a/src/main/java/su/nightexpress/nightcore/menu/impl/ConfigMenu.java +++ b/src/main/java/su/nightexpress/nightcore/menu/impl/ConfigMenu.java @@ -27,9 +27,9 @@ public abstract class ConfigMenu

extends AbstractMenu protected final Map handlerMap; protected String itemSection; - public ConfigMenu(@NotNull P plugin, @NotNull FileConfig cfg) { + public ConfigMenu(@NotNull P plugin, @NotNull FileConfig config) { super(plugin); - this.cfg = cfg; + this.cfg = config; this.handlerMap = new HashMap<>(); this.itemSection = DEFAULT_ITEM_SECTION; @@ -111,10 +111,12 @@ public void loadConfig() { comments.add("> Slots: Button slots. From [0] to [Size - 1]. Split with commas."); comments.add("> Click_Commands: Execute custom commands on click. " + Plugins.PLACEHOLDER_API + " available here."); comments.add(" Available click types: " + String.join(", ", Lists.getEnums(ClickType.class))); + comments.add(" Use prefix '" + Players.PLAYER_COMMAND_PREFIX + "' to run command by a player."); comments.add(" Click_Commands:"); comments.add(" LEFT:"); comments.add(" - say Hello"); comments.add(" - give " + Placeholders.PLAYER_NAME + " diamond 1"); + comments.add(" - " + Players.PLAYER_COMMAND_PREFIX + " menu open shops"); comments.add("=".repeat(50)); this.cfg.setComments(this.itemSection, comments); this.cfg.saveChanges(); diff --git a/src/main/java/su/nightexpress/nightcore/menu/impl/EditorMenu.java b/src/main/java/su/nightexpress/nightcore/menu/impl/EditorMenu.java index be2f507..89c7f26 100644 --- a/src/main/java/su/nightexpress/nightcore/menu/impl/EditorMenu.java +++ b/src/main/java/su/nightexpress/nightcore/menu/impl/EditorMenu.java @@ -11,6 +11,7 @@ import su.nightexpress.nightcore.dialog.DialogHandler; import su.nightexpress.nightcore.language.entry.LangItem; import su.nightexpress.nightcore.language.entry.LangString; +import su.nightexpress.nightcore.menu.MenuSize; import su.nightexpress.nightcore.menu.MenuViewer; import su.nightexpress.nightcore.menu.item.ItemHandler; import su.nightexpress.nightcore.menu.item.MenuItem; @@ -26,11 +27,17 @@ public abstract class EditorMenu

extends AbstractM protected final ViewLink link; + @Deprecated public EditorMenu(@NotNull P plugin, @NotNull String title, int size) { super(plugin, title, size); this.link = new ViewLink<>(); } + public EditorMenu(@NotNull P plugin, @NotNull String title, @NotNull MenuSize size) { + super(plugin, title, size); + this.link = new ViewLink<>(); + } + @NotNull @Override public ViewLink getLink() { @@ -107,7 +114,7 @@ public MenuItem addItem(@NotNull Material material, @NotNull LangItem locale, in public MenuItem addItem(@NotNull ItemStack item, @NotNull LangItem locale, int slot, @NotNull EditorHandler handler) { ItemReplacer.create(item).trimmed().hideFlags().readLocale(locale).writeMeta(); MenuItem menuItem = new MenuItem(item).setPriority(100).setSlots(slot) - .setHandler((viewer, event) -> handler.handle(viewer, event, this.getObject(viewer))); + .setHandler((viewer, event) -> handler.handle(viewer, event, this.getLink(viewer))); this.addItem(menuItem); return menuItem; } @@ -132,6 +139,7 @@ public Dialog handleInput(@NotNull Player player, @NotNull WrappedMessage prompt } @NotNull + @Deprecated public Dialog handleInput(@NotNull Player player, @NotNull String prompt, @NotNull DialogHandler handler) { this.runNextTick(player::closeInventory); @@ -140,20 +148,24 @@ public Dialog handleInput(@NotNull Player player, @NotNull String prompt, @NotNu return dialog; } + @Deprecated public void editObject(@NotNull MenuViewer viewer, @NotNull Consumer consumer) { this.editObject(viewer.getPlayer(), consumer); } + @Deprecated public void editObject(@NotNull Player player, @NotNull Consumer consumer) { - consumer.accept(this.getObject(player)); + consumer.accept(this.getLink(player)); } @NotNull + @Deprecated public T getObject(@NotNull MenuViewer viewer) { return this.getLink().get(viewer); } @NotNull + @Deprecated public T getObject(@NotNull Player player) { return this.getLink().get(player); } diff --git a/src/main/java/su/nightexpress/nightcore/menu/item/ItemHandler.java b/src/main/java/su/nightexpress/nightcore/menu/item/ItemHandler.java index c1a9f5e..2fcfc5f 100644 --- a/src/main/java/su/nightexpress/nightcore/menu/item/ItemHandler.java +++ b/src/main/java/su/nightexpress/nightcore/menu/item/ItemHandler.java @@ -46,7 +46,7 @@ public ItemHandler(@NotNull String name, @Nullable ClickAction clickAction, @Nul } /** - * The main purpose of this method is to quickly created ItemHandler object for non-configurable GUIs. + * The main purpose of this method is to quickly create ItemHandler object for non-configurable GUIs. *

* Do NOT use this for items requires specific handler name. * @param action Click action diff --git a/src/main/java/su/nightexpress/nightcore/menu/link/Linked.java b/src/main/java/su/nightexpress/nightcore/menu/link/Linked.java index 3d6852a..de2c41a 100644 --- a/src/main/java/su/nightexpress/nightcore/menu/link/Linked.java +++ b/src/main/java/su/nightexpress/nightcore/menu/link/Linked.java @@ -17,6 +17,10 @@ default T getLink(@NotNull Player player) { return this.getLink().get(player); } + default boolean cleanOnClose() { + return true; + } + default boolean open(@NotNull Player player, @NotNull T obj) { this.getLink().set(player, obj); diff --git a/src/main/java/su/nightexpress/nightcore/util/BukkitThing.java b/src/main/java/su/nightexpress/nightcore/util/BukkitThing.java index 4ed3c6e..e3a4ca8 100644 --- a/src/main/java/su/nightexpress/nightcore/util/BukkitThing.java +++ b/src/main/java/su/nightexpress/nightcore/util/BukkitThing.java @@ -1,12 +1,10 @@ package su.nightexpress.nightcore.util; -import org.bukkit.Keyed; -import org.bukkit.Material; -import org.bukkit.NamespacedKey; -import org.bukkit.Registry; +import org.bukkit.*; import org.bukkit.attribute.Attribute; import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.EntityType; +import org.bukkit.potion.PotionEffectType; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -32,11 +30,21 @@ public static Set allFromRegistry(@NotNull Registry regi return registry.stream().collect(Collectors.toSet()); } + @NotNull + public static String toString(@NotNull Keyed keyed) { + return keyed.getKey().getKey(); + } + @Nullable public static Material getMaterial(@NotNull String name) { return fromRegistry(Registry.MATERIAL, name); } + @NotNull + public static Set getMaterials() { + return allFromRegistry(Registry.MATERIAL); + } + @NotNull public static Set getEnchantments() { return allFromRegistry(Registry.ENCHANTMENT); @@ -59,4 +67,14 @@ public static EntityType getEntityType(@NotNull String name) { public static Attribute getAttribute(@NotNull String name) { return fromRegistry(Registry.ATTRIBUTE, name); } + + @Nullable + public static PotionEffectType getPotionEffect(@NotNull String name) { + return fromRegistry(Registry.EFFECT, name); + } + + @Nullable + public static Sound getSound(@NotNull String name) { + return fromRegistry(Registry.SOUNDS, name); + } } diff --git a/src/main/java/su/nightexpress/nightcore/util/CommandUtil.java b/src/main/java/su/nightexpress/nightcore/util/CommandUtil.java index 74f47b0..c5ea267 100644 --- a/src/main/java/su/nightexpress/nightcore/util/CommandUtil.java +++ b/src/main/java/su/nightexpress/nightcore/util/CommandUtil.java @@ -3,9 +3,13 @@ import org.bukkit.Bukkit; import org.bukkit.command.Command; import org.bukkit.command.SimpleCommandMap; +import org.bukkit.entity.Player; import org.bukkit.plugin.Plugin; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import su.nightexpress.nightcore.command.api.NightPluginCommand; +import su.nightexpress.nightcore.command.experimental.CommandContext; +import su.nightexpress.nightcore.command.experimental.argument.ParsedArguments; import su.nightexpress.nightcore.command.impl.WrappedCommand; import java.util.*; @@ -28,6 +32,10 @@ public static void register(@NotNull Plugin plugin, @NotNull NightPluginCommand } } + public static boolean register(@NotNull Plugin plugin, @NotNull WrappedCommand wrappedCommand) { + return COMMAND_MAP.register(plugin.getName(), wrappedCommand); + } + /*public static void syncCommands() { // Fix tab completer when registerd on runtime Server server = Bukkit.getServer(); @@ -82,4 +90,20 @@ public static String getCommandName(@NotNull String str) { return name; } + + @Nullable + public static Player getPlayerOrSender(@NotNull CommandContext context, @NotNull ParsedArguments arguments, @NotNull String name) { + Player player; + if (arguments.hasArgument(name)) { + player = arguments.getPlayerArgument(name); + } + else { + if (context.getExecutor() == null) { + context.errorPlayerOnly(); + return null; + } + player = context.getExecutor(); + } + return player; + } } diff --git a/src/main/java/su/nightexpress/nightcore/util/EntityUtil.java b/src/main/java/su/nightexpress/nightcore/util/EntityUtil.java index 6c9b1f0..5f2dcb9 100644 --- a/src/main/java/su/nightexpress/nightcore/util/EntityUtil.java +++ b/src/main/java/su/nightexpress/nightcore/util/EntityUtil.java @@ -10,6 +10,7 @@ import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import su.nightexpress.nightcore.NightCore; import su.nightexpress.nightcore.util.random.Rnd; import java.util.Collections; @@ -19,12 +20,39 @@ public class EntityUtil { - private static final Class NMS_ENTITY = Reflex.getClass("net.minecraft.world.entity", "Entity"); - private static final String ENTITY_COUNTER_NAME = Version.isAtLeast(Version.V1_19_R3) ? "d" : "c"; - public static final AtomicInteger ENTITY_COUNTER = (AtomicInteger) Reflex.getFieldValue(NMS_ENTITY, ENTITY_COUNTER_NAME); + private static AtomicInteger entityCounter; + + public static boolean setupEntityCounter(@NotNull NightCore core) { + Class entityClass = Reflex.getClass("net.minecraft.world.entity", "Entity"); + if (entityClass == null) { + core.error("Could not find NMS Entity class!"); + return false; + } + + String fieldName = "c"; + if (Version.isAtLeast(Version.V1_19_R3) && Version.isBehind(Version.MC_1_20_6)) { + fieldName = "d"; + } + + Object object = Reflex.getFieldValue(entityClass, fieldName); + if (!(object instanceof AtomicInteger atomicInteger)) { + if (object == null) { + core.error("Could not find entity counter field!"); + } + else core.error("Field '" + fieldName + "' in " + entityClass.getName() + " class is " + object.getClass().getName() + " (expected AtomicInteger)"); + return false; + } + + entityCounter = atomicInteger; + return true; + } + + public static AtomicInteger getEntityCounter() { + return entityCounter; + } public static int nextEntityId() { - return ENTITY_COUNTER == null ? Rnd.nextInt(9999) : ENTITY_COUNTER.incrementAndGet(); + return entityCounter == null ? Rnd.nextInt(9999) : entityCounter.incrementAndGet(); } public static double getAttribute(@NotNull LivingEntity entity, @NotNull Attribute attribute) { diff --git a/src/main/java/su/nightexpress/nightcore/util/ItemNbt.java b/src/main/java/su/nightexpress/nightcore/util/ItemNbt.java new file mode 100644 index 0000000..658cc37 --- /dev/null +++ b/src/main/java/su/nightexpress/nightcore/util/ItemNbt.java @@ -0,0 +1,168 @@ +package su.nightexpress.nightcore.util; + +import org.bukkit.Bukkit; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import su.nightexpress.nightcore.NightCore; + +import java.io.*; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; + +public class ItemNbt { + + private static final Class ITEM_STACK_CLASS = Reflex.getClass("net.minecraft.world.item", "ItemStack"); + private static final Class COMPOUND_TAG_CLASS = Reflex.getClass("net.minecraft.nbt", "NBTTagCompound"); + private static final Class NBT_IO_CLASS = Reflex.getClass("net.minecraft.nbt", "NBTCompressedStreamTools"); + + private static final Class CRAFT_ITEM_STACK_CLASS = Reflex.getClass(Version.CRAFTBUKKIT_PACKAGE + ".inventory", "CraftItemStack"); + + private static final Method CRAFT_ITEM_STACK_AS_NMS_COPY = Reflex.getMethod(CRAFT_ITEM_STACK_CLASS, "asNMSCopy", ItemStack.class); + private static final Method CRAFT_ITEM_STACK_AS_BUKKIT_COPY = Reflex.getMethod(CRAFT_ITEM_STACK_CLASS, "asBukkitCopy", ITEM_STACK_CLASS); + + private static final Method NBT_IO_WRITE = Reflex.getMethod(NBT_IO_CLASS, "a", COMPOUND_TAG_CLASS, DataOutput.class); + private static final Method NBT_IO_READ = Reflex.getMethod(NBT_IO_CLASS, "a", DataInput.class); + + // For 1.20.6+ + private static Method MINECRAFT_SERVER_REGISTRY_ACCESS; + private static Method ITEM_STACK_PARSE_OPTIONAL; + private static Method ITEM_STACK_SAVE_OPTIONAL; + + // For 1.20.4 and below. + private static Constructor NBT_TAG_COMPOUND_NEW; + private static Method NMS_ITEM_OF; + private static Method NMS_SAVE; + + static { + if (Version.isAtLeast(Version.MC_1_20_6)) { + Class minecraftServerClass = Reflex.getClass("net.minecraft.server", "MinecraftServer"); + Class holderLookupProviderClass = Reflex.getInnerClass("net.minecraft.core.HolderLookup", "Provider"); + + MINECRAFT_SERVER_REGISTRY_ACCESS = Reflex.getMethod(minecraftServerClass, "bc"); + ITEM_STACK_PARSE_OPTIONAL = Reflex.getMethod(ITEM_STACK_CLASS, "a", holderLookupProviderClass, COMPOUND_TAG_CLASS); + ITEM_STACK_SAVE_OPTIONAL = Reflex.getMethod(ITEM_STACK_CLASS, "b", holderLookupProviderClass); + } + else { + NBT_TAG_COMPOUND_NEW = Reflex.getConstructor(COMPOUND_TAG_CLASS); + NMS_ITEM_OF = Reflex.getMethod(ITEM_STACK_CLASS, "a", COMPOUND_TAG_CLASS); + NMS_SAVE = Reflex.getMethod(ITEM_STACK_CLASS, "b", COMPOUND_TAG_CLASS); + } + } + + private static boolean useRegistry; + private static Object registryAccess; + + public static boolean setup(@NotNull NightCore core) { + if (Version.isBehind(Version.MC_1_20_6)) return true; + + useRegistry = true; + + Class craftServerClass = Reflex.getClass(Version.CRAFTBUKKIT_PACKAGE, "CraftServer"); + if (craftServerClass == null) { + core.error("Could not find 'CraftServer' class in craftbukkit package: '" + Version.CRAFTBUKKIT_PACKAGE + "'."); + return false; + } + + Method getServer = Reflex.getMethod(craftServerClass, "getServer"); + if (getServer == null || MINECRAFT_SERVER_REGISTRY_ACCESS == null) { + core.error("Could not find proper class(es) for ItemStack compression util."); + return false; + } + + try { + Object craftServer = craftServerClass.cast(Bukkit.getServer()); + Object minecraftServer = getServer.invoke(craftServer); + registryAccess = MINECRAFT_SERVER_REGISTRY_ACCESS.invoke(minecraftServer); + return true; + } + catch (ReflectiveOperationException exception) { + exception.printStackTrace(); + return false; + } + } + + @Nullable + public static String compress(@NotNull ItemStack item) { + if (CRAFT_ITEM_STACK_AS_NMS_COPY == null || NBT_IO_WRITE == null) { + return null; + } + + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + DataOutputStream dataOutput = new DataOutputStream(outputStream); + try { + Object compoundTag; + Object itemStack = CRAFT_ITEM_STACK_AS_NMS_COPY.invoke(null, item); + + if (useRegistry) { + if (ITEM_STACK_SAVE_OPTIONAL == null) return null; + + compoundTag = ITEM_STACK_SAVE_OPTIONAL.invoke(itemStack, registryAccess); + } + else { + if (NBT_TAG_COMPOUND_NEW == null || NMS_SAVE == null) return null; + + compoundTag = NBT_TAG_COMPOUND_NEW.newInstance(); + NMS_SAVE.invoke(itemStack, compoundTag); + } + + NBT_IO_WRITE.invoke(null, compoundTag, dataOutput); + + return new BigInteger(1, outputStream.toByteArray()).toString(32); + } + catch (ReflectiveOperationException exception) { + exception.printStackTrace(); + return null; + } + } + + @Nullable + public static ItemStack decompress(@NotNull String compressed) { + if (NBT_IO_READ == null || CRAFT_ITEM_STACK_AS_BUKKIT_COPY == null) { + throw new UnsupportedOperationException("Unsupported server version!"); + } + + ByteArrayInputStream inputStream = new ByteArrayInputStream(new BigInteger(compressed, 32).toByteArray()); + try { + Object compoundTag = NBT_IO_READ.invoke(null, new DataInputStream(inputStream)); + Object itemStack; + + if (useRegistry) { + if (ITEM_STACK_PARSE_OPTIONAL == null) return null; + + itemStack = ITEM_STACK_PARSE_OPTIONAL.invoke(null, registryAccess, compoundTag); + } + else { + if (NMS_ITEM_OF == null) return null; + + itemStack = NMS_ITEM_OF.invoke(null, compoundTag); + } + + return (ItemStack) CRAFT_ITEM_STACK_AS_BUKKIT_COPY.invoke(null, itemStack); + } + catch (ReflectiveOperationException exception) { + exception.printStackTrace(); + return null; + } + } + + @NotNull + public static List compress(@NotNull ItemStack[] items) { + return compress(Arrays.asList(items)); + } + + @NotNull + public static List compress(@NotNull List items) { + return new ArrayList<>(items.stream().map(ItemNbt::compress).filter(Objects::nonNull).toList()); + } + + public static ItemStack[] decompress(@NotNull List list) { + List items = list.stream().map(ItemNbt::decompress).filter(Objects::nonNull).toList(); + return items.toArray(new ItemStack[list.size()]); + } +} diff --git a/src/main/java/su/nightexpress/nightcore/util/ItemReplacer.java b/src/main/java/su/nightexpress/nightcore/util/ItemReplacer.java index 98edfb8..10f852c 100644 --- a/src/main/java/su/nightexpress/nightcore/util/ItemReplacer.java +++ b/src/main/java/su/nightexpress/nightcore/util/ItemReplacer.java @@ -29,6 +29,7 @@ public class ItemReplacer { private boolean trimLore; private boolean hideFlags; + private Player papi; public ItemReplacer(@NotNull ItemStack item) { this(item, item.getItemMeta()); @@ -44,6 +45,16 @@ public ItemReplacer(@Nullable ItemStack item, @Nullable ItemMeta meta) { this.placeholderMap = new PlaceholderMap(); } + @NotNull + public static ItemReplacer create(@NotNull ItemStack item) { + return new ItemReplacer(item); + } + + @NotNull + public static ItemReplacer create(@NotNull ItemMeta meta) { + return new ItemReplacer(meta); + } + @NotNull public ItemReplacer readMeta() { if (this.hasMeta()) { @@ -66,6 +77,7 @@ public void writeMeta() { if (!this.hasMeta()) return; this.replace(this.placeholderMap.replacer()); + if (this.papi != null) this.injectPlaceholderAPI(this.papi); this.meta.setDisplayName(this.getDisplayName() == null ? null : NightMessage.asLegacy(this.getDisplayName())); this.meta.setLore(this.packTrimmedLore()); @@ -79,24 +91,33 @@ public void writeMeta() { } } - @NotNull - public static ItemReplacer create(@NotNull ItemStack item) { - return new ItemReplacer(item); + public static void replace(@NotNull ItemStack item, @NotNull UnaryOperator replacer) { + create(item).trimmed().readMeta().replace(replacer).writeMeta(); } - @NotNull - public static ItemReplacer create(@NotNull ItemMeta meta) { - return new ItemReplacer(meta); + @Deprecated + public static void replace(@NotNull ItemMeta meta, @NotNull UnaryOperator replacer) { + create(meta).trimmed().readMeta().replace(replacer).writeMeta(); } - public static void replace(@NotNull ItemStack item, @NotNull UnaryOperator replacer) { + public static void replace(@NotNull ItemStack item, @NotNull PlaceholderMap replacer) { create(item).trimmed().readMeta().replace(replacer).writeMeta(); } - public static void replace(@NotNull ItemMeta meta, @NotNull UnaryOperator replacer) { + @Deprecated + public static void replace(@NotNull ItemMeta meta, @NotNull PlaceholderMap replacer) { create(meta).trimmed().readMeta().replace(replacer).writeMeta(); } + public static void replacePlaceholderAPI(@NotNull ItemStack item, @NotNull Player player) { + create(item).trimmed().readMeta().replacePlaceholderAPI(player).writeMeta(); + } + + @Deprecated + public static void replacePlaceholderAPI(@NotNull ItemMeta meta, @NotNull Player player) { + create(meta).trimmed().readMeta().replacePlaceholderAPI(player).writeMeta(); + } + public boolean hasMeta() { return this.meta != null; } @@ -170,9 +191,9 @@ public ItemReplacer replace(@NotNull UnaryOperator replacer) { @NotNull public ItemReplacer replacePlaceholderAPI(@NotNull Player player) { - if (!Plugins.hasPlaceholderAPI()) return this; - - this.replace(str -> PlaceholderAPI.setPlaceholders(player, str)); + if (Plugins.hasPlaceholderAPI()) { + this.papi = player; + } return this; } @@ -202,6 +223,14 @@ public ItemReplacer injectLore(@NotNull String placeholder, @NotNull List PlaceholderAPI.setPlaceholders(player, str)); + } + return this; + } + @NotNull public ItemReplacer replaceLoreTrail(@NotNull String placeholder, @NotNull List replacer) { if (this.getLore() == null) return this; diff --git a/src/main/java/su/nightexpress/nightcore/util/ItemUtil.java b/src/main/java/su/nightexpress/nightcore/util/ItemUtil.java index f5f0320..31a58f1 100644 --- a/src/main/java/su/nightexpress/nightcore/util/ItemUtil.java +++ b/src/main/java/su/nightexpress/nightcore/util/ItemUtil.java @@ -15,35 +15,15 @@ import org.jetbrains.annotations.Nullable; import su.nightexpress.nightcore.language.LangAssets; -import java.io.*; -import java.lang.reflect.Constructor; import java.lang.reflect.Method; -import java.math.BigInteger; import java.net.URL; import java.util.*; import java.util.function.Consumer; public class ItemUtil { - //private static final String VERSION = Version.getProtocol(); private static final String TEXTURES_HOST = "http://textures.minecraft.net/texture/"; - private static final Class NBT_TAG_COMPOUND = Reflex.getClass("net.minecraft.nbt", "NBTTagCompound"); - private static final Class NMS_ITEM = Reflex.getClass("net.minecraft.world.item", "ItemStack"); - private static final Class CRAFT_ITEM_STACK = Reflex.getClass(Version.CRAFTBUKKIT_PACKAGE + ".inventory", "CraftItemStack"); - private static final Class NBT_IO = Reflex.getClass("net.minecraft.nbt", "NBTCompressedStreamTools"); - - private static final Constructor NBT_TAG_COMPOUND_NEW = Reflex.getConstructor(NBT_TAG_COMPOUND); - - private static final Method AS_NMS_COPY = Reflex.getMethod(CRAFT_ITEM_STACK, "asNMSCopy", ItemStack.class); - private static final Method AS_BUKKIT_COPY = Reflex.getMethod(CRAFT_ITEM_STACK, "asBukkitCopy", NMS_ITEM); - - private static final Method NMS_ITEM_OF = Reflex.getMethod(NMS_ITEM, "a", NBT_TAG_COMPOUND); - private static final Method NMS_SAVE = Reflex.getMethod(NMS_ITEM, "b", NBT_TAG_COMPOUND); - - private static final Method NBT_IO_WRITE = Reflex.getMethod(NBT_IO, "a", NBT_TAG_COMPOUND, DataOutput.class); - private static final Method NBT_IO_READ = Reflex.getMethod(NBT_IO, "a", DataInput.class); - @NotNull public static String getItemName(@NotNull ItemStack item) { ItemMeta meta = item.getItemMeta(); @@ -275,60 +255,32 @@ public static EquipmentSlot getEquipmentSlot(@NotNull ItemStack item) { } @Nullable + @Deprecated public static String compress(@NotNull ItemStack item) { - if (NBT_TAG_COMPOUND_NEW == null || AS_NMS_COPY == null || NMS_SAVE == null || NBT_IO_WRITE == null) { - //throw new UnsupportedOperationException("Unsupported server version!"); - return null; - } - - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - DataOutputStream dataOutput = new DataOutputStream(outputStream); - - try { - Object nbtTagCompoundItem = NBT_TAG_COMPOUND_NEW.newInstance(); - Object nmsItem = AS_NMS_COPY.invoke(null, item); - NMS_SAVE.invoke(nmsItem, nbtTagCompoundItem); - NBT_IO_WRITE.invoke(null, nbtTagCompoundItem, dataOutput); - return new BigInteger(1, outputStream.toByteArray()).toString(32); - } - catch (ReflectiveOperationException e) { - e.printStackTrace(); - return null; - } + return ItemNbt.compress(item); } @Nullable + @Deprecated public static ItemStack decompress(@NotNull String compressed) { - if (NBT_IO_READ == null || NMS_ITEM_OF == null || AS_BUKKIT_COPY == null) { - throw new UnsupportedOperationException("Unsupported server version!"); - } - - ByteArrayInputStream inputStream = new ByteArrayInputStream(new BigInteger(compressed, 32).toByteArray()); - - Object nbtTagCompoundRoot; - try { - nbtTagCompoundRoot = NBT_IO_READ.invoke(null, new DataInputStream(inputStream)); - Object nmsItem = NMS_ITEM_OF.invoke(null, nbtTagCompoundRoot); - return (ItemStack) AS_BUKKIT_COPY.invoke(null, nmsItem); - } - catch (ReflectiveOperationException e) { - e.printStackTrace(); - return null; - } + return ItemNbt.decompress(compressed); } @NotNull + @Deprecated public static List compress(@NotNull ItemStack[] items) { - return compress(Arrays.asList(items)); + return ItemNbt.compress(Arrays.asList(items)); } @NotNull + @Deprecated public static List compress(@NotNull List items) { - return new ArrayList<>(items.stream().map(ItemUtil::compress).filter(Objects::nonNull).toList()); + return new ArrayList<>(items.stream().map(ItemNbt::compress).filter(Objects::nonNull).toList()); } + @Deprecated public static ItemStack[] decompress(@NotNull List list) { - List items = list.stream().map(ItemUtil::decompress).filter(Objects::nonNull).toList(); + List items = list.stream().map(ItemNbt::decompress).filter(Objects::nonNull).toList(); return items.toArray(new ItemStack[list.size()]); } } diff --git a/src/main/java/su/nightexpress/nightcore/util/Lists.java b/src/main/java/su/nightexpress/nightcore/util/Lists.java index f2b22bb..c1f98b3 100644 --- a/src/main/java/su/nightexpress/nightcore/util/Lists.java +++ b/src/main/java/su/nightexpress/nightcore/util/Lists.java @@ -1,5 +1,6 @@ package su.nightexpress.nightcore.util; +import org.bukkit.Bukkit; import org.bukkit.generator.WorldInfo; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -13,7 +14,7 @@ public class Lists { @NotNull public static List worldNames() { - return Plugins.CORE.getServer().getWorlds().stream().map(WorldInfo::getName).toList(); + return Bukkit.getServer().getWorlds().stream().map(WorldInfo::getName).toList(); } public static int indexOf(Object[] array, @NotNull Object objectToFind) { diff --git a/src/main/java/su/nightexpress/nightcore/util/LocationUtil.java b/src/main/java/su/nightexpress/nightcore/util/LocationUtil.java index c99ee07..c51152d 100644 --- a/src/main/java/su/nightexpress/nightcore/util/LocationUtil.java +++ b/src/main/java/su/nightexpress/nightcore/util/LocationUtil.java @@ -65,7 +65,7 @@ public static Location getCenter(@NotNull Location location) { @NotNull public static Location getCenter(@NotNull Location location, boolean doVertical) { - Location centered = location.clone(); + //Location centered = location.clone(); location.setX(location.getBlockX() + 0.5); location.setY(location.getBlockY() + (doVertical ? 0.5 : 0)); location.setZ(location.getBlockZ() + 0.5); diff --git a/src/main/java/su/nightexpress/nightcore/util/NumberUtil.java b/src/main/java/su/nightexpress/nightcore/util/NumberUtil.java index 6e44e07..66d03f6 100644 --- a/src/main/java/su/nightexpress/nightcore/util/NumberUtil.java +++ b/src/main/java/su/nightexpress/nightcore/util/NumberUtil.java @@ -5,6 +5,7 @@ import su.nightexpress.nightcore.core.CoreLang; import java.math.BigDecimal; +import java.util.Optional; import java.util.TreeMap; import java.util.function.Supplier; @@ -100,15 +101,7 @@ public static double getDouble(@NotNull String input, double defaultValue) { } public static double getAnyDouble(@NotNull String input, double defaultValue) { - try { - double amount = Double.parseDouble(input); - if (!Double.isNaN(amount) && !Double.isInfinite(amount)) { - return amount; - } - } - catch (NumberFormatException ignored) {} - - return defaultValue; + return parseDouble(input).orElse(defaultValue); } public static int getInteger(@NotNull String input) { @@ -120,12 +113,31 @@ public static int getInteger(@NotNull String input, int defaultValue) { } public static int getAnyInteger(@NotNull String input, int defaultValue) { + return parseInteger(input).orElse(defaultValue); + } + + @NotNull + public static Optional parseInteger(@NotNull String input) { try { - return Integer.parseInt(input); + return Optional.of(Integer.parseInt(input)); } - catch (NumberFormatException ignored) {} + catch (NumberFormatException exception) { + return Optional.empty(); + } + } - return defaultValue; + @NotNull + public static Optional parseDouble(@NotNull String input) { + try { + double amount = Double.parseDouble(input); + if (!Double.isNaN(amount) && !Double.isInfinite(amount)) { + return Optional.of(amount); + } + return Optional.empty(); + } + catch (NumberFormatException exception) { + return Optional.empty(); + } } public static int[] getIntArray(@NotNull String str) { diff --git a/src/main/java/su/nightexpress/nightcore/util/PDCUtil.java b/src/main/java/su/nightexpress/nightcore/util/PDCUtil.java index e26b719..7164815 100644 --- a/src/main/java/su/nightexpress/nightcore/util/PDCUtil.java +++ b/src/main/java/su/nightexpress/nightcore/util/PDCUtil.java @@ -88,11 +88,6 @@ public static void set(@NotNull ItemStack item, @NotNull NamespacedKey key, @Nullable Z value) { ItemUtil.editMeta(item, meta -> set(meta, dataType, key, value)); - /*ItemMeta meta = item.getItemMeta(); - if (meta == null) return; - - set(meta, dataType, key, value); - item.setItemMeta(meta);*/ } public static void set(@NotNull PersistentDataHolder holder, @@ -106,26 +101,15 @@ public static void set(@NotNull PersistentDataHolder holder, PersistentDataContainer container = holder.getPersistentDataContainer(); container.set(key, dataType, value); - - /*if (holder instanceof BlockState state) { - state.update(); - }*/ } public static void remove(@NotNull ItemStack holder, @NotNull NamespacedKey key) { - //ItemMeta meta = holder.getItemMeta(); - //if (meta == null) return; - //remove(meta, key); ItemUtil.editMeta(holder, meta -> remove(meta, key)); } public static void remove(@NotNull PersistentDataHolder holder, @NotNull NamespacedKey key) { PersistentDataContainer container = holder.getPersistentDataContainer(); container.remove(key); - - /*if (holder instanceof BlockState state) { - state.update(); - }*/ } @NotNull diff --git a/src/main/java/su/nightexpress/nightcore/util/Players.java b/src/main/java/su/nightexpress/nightcore/util/Players.java index 2b663f3..6b0689e 100644 --- a/src/main/java/su/nightexpress/nightcore/util/Players.java +++ b/src/main/java/su/nightexpress/nightcore/util/Players.java @@ -24,6 +24,8 @@ public class Players { + public static final String PLAYER_COMMAND_PREFIX = "player:"; + @NotNull public static List playerNames() { return playerNames(null); @@ -158,7 +160,9 @@ public static void sendActionBar(@NotNull Player player, @NotNull WrappedMessage } public static void dispatchCommands(@NotNull Player player, @NotNull String... commands) { - dispatchCommands(player, Arrays.asList(commands)); + for (String command : commands) { + dispatchCommand(player, command); + } } public static void dispatchCommands(@NotNull Player player, @NotNull List commands) { @@ -168,13 +172,18 @@ public static void dispatchCommands(@NotNull Player player, @NotNull List readInt(@NotNull FileConfig cfg, @NotNull String path) { - return read(cfg, path, Integer.class); + public static RankMap readInt(@NotNull FileConfig cfg, @NotNull String path, int defaultValue) { + return read(cfg, path, Integer.class, defaultValue); } @NotNull - public static RankMap readDouble(@NotNull FileConfig cfg, @NotNull String path) { - return read(cfg, path, Double.class); + public static RankMap readDouble(@NotNull FileConfig cfg, @NotNull String path, double defaultValue) { + return read(cfg, path, Double.class, defaultValue); } @NotNull - public static RankMap readLong(@NotNull FileConfig cfg, @NotNull String path) { - return read(cfg, path, Long.class); + public static RankMap readLong(@NotNull FileConfig cfg, @NotNull String path, long defaultValue) { + return read(cfg, path, Long.class, defaultValue); } @NotNull - public static RankMap read(@NotNull FileConfig cfg, @NotNull String path, @NotNull Class clazz) { + public static RankMap read(@NotNull FileConfig cfg, @NotNull String path, @NotNull Class clazz, @NotNull T defaultValue) { Map oldMap = new HashMap<>(); if (!cfg.contains(path + ".Mode")) { @@ -80,11 +80,11 @@ public static RankMap read(@NotNull FileConfig cfg, @NotNu "All 'Values' keys will be used to check if player has permission: + ." ).read(cfg); - T defaultValue; + T fallback; if (clazz == Double.class) { - defaultValue = clazz.cast(ConfigValue.create(path + ".Default_Value", -1).read(cfg)); + fallback = clazz.cast(ConfigValue.create(path + ".Default_Value", defaultValue.doubleValue()).read(cfg)); } - else defaultValue = clazz.cast(ConfigValue.create(path + ".Default_Value", -1).read(cfg)); + else fallback = clazz.cast(ConfigValue.create(path + ".Default_Value", defaultValue.intValue()).read(cfg)); Map values = new HashMap<>(); for (String rank : cfg.getSection(path + ".Values")) { @@ -97,7 +97,7 @@ public static RankMap read(@NotNull FileConfig cfg, @NotNu values.put(rank.toLowerCase(), number); } - return new RankMap<>(mode, permissionPrefix, defaultValue, values); + return new RankMap<>(mode, permissionPrefix, fallback, values); } public void write(@NotNull FileConfig cfg, @NotNull String path) { diff --git a/src/main/java/su/nightexpress/nightcore/util/Reflex.java b/src/main/java/su/nightexpress/nightcore/util/Reflex.java index 5f243ac..ad15946 100644 --- a/src/main/java/su/nightexpress/nightcore/util/Reflex.java +++ b/src/main/java/su/nightexpress/nightcore/util/Reflex.java @@ -23,20 +23,20 @@ private static Class getClass(@NotNull String path) { try { return Class.forName(path); } - catch (ClassNotFoundException e) { - e.printStackTrace(); + catch (ClassNotFoundException exception) { + exception.printStackTrace(); return null; } } - public static Constructor getConstructor(@NotNull Class clazz, Class... types) { + public static Constructor getConstructor(@NotNull Class source, Class... types) { try { - Constructor constructor = clazz.getDeclaredConstructor(types); + Constructor constructor = source.getDeclaredConstructor(types); constructor.setAccessible(true); return constructor; } - catch (ReflectiveOperationException e) { - e.printStackTrace(); + catch (ReflectiveOperationException exception) { + exception.printStackTrace(); } return null; } @@ -45,18 +45,18 @@ public static Object invokeConstructor(@NotNull Constructor constructor, Obje try { return constructor.newInstance(obj); } - catch (ReflectiveOperationException e) { - e.printStackTrace(); + catch (ReflectiveOperationException exception) { + exception.printStackTrace(); } - return obj; + return null; } @NotNull - public static List getFields(@NotNull Class clazz, @NotNull Class type) { + public static List getFields(@NotNull Class source, @NotNull Class type) { List list = new ArrayList<>(); - for (Field field : Reflex.getFields(clazz)) { - if (!field.getDeclaringClass().equals(clazz)) continue; + for (Field field : Reflex.getFields(source)) { + if (!field.getDeclaringClass().equals(source)) continue; //if (!field.canAccess(null)) continue; if (!Modifier.isStatic(field.getModifiers())) continue; if (!Modifier.isFinal(field.getModifiers())) continue; @@ -75,10 +75,10 @@ public static List getFields(@NotNull Class clazz, @NotNull Class t } @NotNull - public static List getFields(@NotNull Class type) { + public static List getFields(@NotNull Class source) { List result = new ArrayList<>(); - Class clazz = type; + Class clazz = source; while (clazz != null && clazz != Object.class) { if (!result.isEmpty()) { result.addAll(0, Arrays.asList(clazz.getDeclaredFields())); @@ -92,56 +92,56 @@ public static List getFields(@NotNull Class type) { return result; } - public static Field getField(@NotNull Class clazz, @NotNull String fieldName) { + public static Field getField(@NotNull Class source, @NotNull String name) { try { - return clazz.getDeclaredField(fieldName); + return source.getDeclaredField(name); } - catch (NoSuchFieldException e) { - Class superClass = clazz.getSuperclass(); - return superClass == null ? null : getField(superClass, fieldName); + catch (NoSuchFieldException exception) { + Class superClass = source.getSuperclass(); + return superClass == null ? null : getField(superClass, name); } } - public static Object getFieldValue(@NotNull Object from, @NotNull String fieldName) { + public static Object getFieldValue(@NotNull Object source, @NotNull String name) { try { - Class clazz = from instanceof Class ? (Class) from : from.getClass(); - Field field = getField(clazz, fieldName); + Class clazz = source instanceof Class ? (Class) source : source.getClass(); + Field field = getField(clazz, name); if (field == null) return null; field.setAccessible(true); - return field.get(from); + return field.get(source); } - catch (IllegalAccessException e) { - e.printStackTrace(); + catch (IllegalAccessException exception) { + exception.printStackTrace(); } return null; } - public static boolean setFieldValue(@NotNull Object of, @NotNull String fieldName, @Nullable Object value) { + public static boolean setFieldValue(@NotNull Object source, @NotNull String name, @Nullable Object value) { try { - boolean isStatic = of instanceof Class; - Class clazz = isStatic ? (Class) of : of.getClass(); + boolean isStatic = source instanceof Class; + Class clazz = isStatic ? (Class) source : source.getClass(); - Field field = getField(clazz, fieldName); + Field field = getField(clazz, name); if (field == null) return false; field.setAccessible(true); - field.set(isStatic ? null : of, value); + field.set(isStatic ? null : source, value); return true; } - catch (IllegalAccessException e) { - e.printStackTrace(); + catch (IllegalAccessException exception) { + exception.printStackTrace(); } return false; } - public static Method getMethod(@NotNull Class clazz, @NotNull String fieldName, @NotNull Class... o) { + public static Method getMethod(@NotNull Class source, @NotNull String name, @NotNull Class... params) { try { - return clazz.getDeclaredMethod(fieldName, o); + return source.getDeclaredMethod(name, params); } - catch (NoSuchMethodException e) { - Class superClass = clazz.getSuperclass(); - return superClass == null ? null : getMethod(superClass, fieldName); + catch (NoSuchMethodException exception) { + Class superClass = source.getSuperclass(); + return superClass == null ? null : getMethod(superClass, name); } } @@ -150,8 +150,8 @@ public static Object invokeMethod(@NotNull Method method, @Nullable Object by, @ try { return method.invoke(by, param); } - catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { - e.printStackTrace(); + catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException exception) { + exception.printStackTrace(); } return null; } diff --git a/src/main/java/su/nightexpress/nightcore/util/StringUtil.java b/src/main/java/su/nightexpress/nightcore/util/StringUtil.java index 8caab21..09328b6 100644 --- a/src/main/java/su/nightexpress/nightcore/util/StringUtil.java +++ b/src/main/java/su/nightexpress/nightcore/util/StringUtil.java @@ -13,7 +13,7 @@ public class StringUtil { - private static final Pattern ID_PATTERN = Pattern.compile("[<>\\%\\$\\!\\@\\#\\^\\&\\*\\(\\)\\,\\.\\'\\:\\;\\\"\\}\\]\\{\\[\\=\\+\\`\\~\\\\]");//Pattern.compile("[^a-zA-Zа-яА-Я_0-9]"); + private static final Pattern ID_PATTERN = Pattern.compile("[<>\\%\\$\\!\\@\\#\\^\\&\\*\\(\\)\\,\\.\\'\\:\\;\\\"\\}\\]\\{\\[\\=\\+\\`\\~\\\\]"); private static final Pattern ID_STRICT_PATTERN = Pattern.compile("[^a-zA-Zа-яА-Я_0-9]"); @NotNull diff --git a/src/main/java/su/nightexpress/nightcore/util/Version.java b/src/main/java/su/nightexpress/nightcore/util/Version.java index 93c2108..550f1fc 100644 --- a/src/main/java/su/nightexpress/nightcore/util/Version.java +++ b/src/main/java/su/nightexpress/nightcore/util/Version.java @@ -12,6 +12,7 @@ public enum Version { V1_20_R1("1.20.1", true), V1_20_R2("1.20.2", true), V1_20_R3("1.20.4"), + MC_1_20_6("1.20.6"), UNKNOWN("Unknown"), ; @@ -34,10 +35,7 @@ public enum Version { @NotNull @Deprecated public static String getProtocol() { - return Bukkit.getServer().getBukkitVersion();//.split("-")[0]; - - //String[] split = Bukkit.getServer().getClass().getPackage().getName().split("\\."); - //return split[split.length - 1]; + return Bukkit.getServer().getBukkitVersion(); } @NotNull @@ -45,7 +43,6 @@ public static Version getCurrent() { if (current == null) { String protocol = Bukkit.getServer().getBukkitVersion(); current = Stream.of(values()).filter(version -> protocol.startsWith(version.getLocalized())).findFirst().orElse(UNKNOWN); - //current = StringUtil.getEnum(getProtocol(), Version.class).orElse(UNKNOWN); } return current; } diff --git a/src/main/java/su/nightexpress/nightcore/util/message/NexComponent.java b/src/main/java/su/nightexpress/nightcore/util/message/NexComponent.java index b9cf433..cdf46be 100644 --- a/src/main/java/su/nightexpress/nightcore/util/message/NexComponent.java +++ b/src/main/java/su/nightexpress/nightcore/util/message/NexComponent.java @@ -9,7 +9,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import su.nightexpress.nightcore.util.Colorizer; -import su.nightexpress.nightcore.util.ItemUtil; +import su.nightexpress.nightcore.util.ItemNbt; import java.util.List; @@ -76,7 +76,7 @@ public NexComponent addClickEvent(@NotNull ClickEvent.Action action, @NotNull St public NexComponent addHoverEvent(@NotNull HoverEvent.Action action, @NotNull String value) { return switch (action) { case SHOW_ITEM -> { - ItemStack item = ItemUtil.decompress(value); + ItemStack item = ItemNbt.decompress(value); yield this.showItem(item == null ? new ItemStack(Material.AIR) : item); } case SHOW_TEXT -> this.showText(value); diff --git a/src/main/java/su/nightexpress/nightcore/util/placeholder/PlaceholderMap.java b/src/main/java/su/nightexpress/nightcore/util/placeholder/PlaceholderMap.java index 2b38b97..fc11e22 100644 --- a/src/main/java/su/nightexpress/nightcore/util/placeholder/PlaceholderMap.java +++ b/src/main/java/su/nightexpress/nightcore/util/placeholder/PlaceholderMap.java @@ -50,7 +50,7 @@ public List>> getKeys() { @NotNull public PlaceholderMap add(@NotNull PlaceholderMap other) { - this.getKeys().addAll(other.getKeys()); + this.keys.addAll(other.getKeys()); return this; } @@ -62,16 +62,16 @@ public PlaceholderMap add(@NotNull String key, @NotNull String replacer) { @NotNull public PlaceholderMap add(@NotNull String key, @NotNull Supplier replacer) { - this.getKeys().add(Pair.of(key, replacer)); + this.keys.add(Pair.of(key, replacer)); return this; } public void clear() { - this.getKeys().clear(); + this.keys.clear(); } @NotNull public UnaryOperator replacer() { - return str -> StringUtil.replaceEach(str, this.getKeys()); + return str -> StringUtil.replaceEach(str, this.keys); } } diff --git a/src/main/java/su/nightexpress/nightcore/util/text/NightMessage.java b/src/main/java/su/nightexpress/nightcore/util/text/NightMessage.java index 651da81..e0d4982 100644 --- a/src/main/java/su/nightexpress/nightcore/util/text/NightMessage.java +++ b/src/main/java/su/nightexpress/nightcore/util/text/NightMessage.java @@ -57,9 +57,9 @@ public static void registerTags(@NotNull Tag... tags) { } } - public static void registerTag(@NotNull Tag tag, @NotNull String... aliases) { + public static void registerTag(@NotNull Tag tag) { TAG_MAP.put(tag.getName(), tag); - for (String alias : aliases) { + for (String alias : tag.getAliases()) { TAG_MAP.put(alias, tag); } } @@ -74,11 +74,20 @@ public static String clean(@NotNull String string) { return create(string, TagPool.NONE).toLegacy(); } + @NotNull + public static String asJson(@NotNull String string) { + return create(string).toJson(); + } + @NotNull public static String asLegacy(@NotNull String string) { return create(string).toLegacy(); } + public static BaseComponent asComponent(@NotNull String string) { + return create(string).toComponent(); + } + @NotNull public static List asLegacy(@NotNull List string) { List list = new ArrayList<>(); @@ -115,8 +124,6 @@ public static WrappedMessage from(@NotNull String string, @NotNull TagPool tagPo return new WrappedMessage(string, tagPool); } - - public static BaseComponent[] parse(@NotNull String string) { return parse(string, TagPool.ALL); } diff --git a/src/main/java/su/nightexpress/nightcore/util/text/WrappedMessage.java b/src/main/java/su/nightexpress/nightcore/util/text/WrappedMessage.java index 7559ad6..6a2a19f 100644 --- a/src/main/java/su/nightexpress/nightcore/util/text/WrappedMessage.java +++ b/src/main/java/su/nightexpress/nightcore/util/text/WrappedMessage.java @@ -2,6 +2,7 @@ import net.md_5.bungee.api.chat.BaseComponent; import net.md_5.bungee.api.chat.TextComponent; +import net.md_5.bungee.chat.ComponentSerializer; import org.bukkit.command.CommandSender; import org.jetbrains.annotations.NotNull; import su.nightexpress.nightcore.util.text.tag.TagPool; @@ -50,6 +51,16 @@ public String toLegacy() { return TextComponent.toLegacyText(this.parseIfAbsent()); } + @NotNull + public String toJson() { + return ComponentSerializer.toString(this.parseIfAbsent()); + } + + @NotNull + public BaseComponent toComponent() { + return TextComponent.fromArray(this.parseIfAbsent()); + } + @NotNull public WrappedMessage replace(@NotNull String what, @NotNull Object object) { return this.replace(str -> str.replace(what, String.valueOf(object))); diff --git a/src/main/java/su/nightexpress/nightcore/util/text/WrappedText.java b/src/main/java/su/nightexpress/nightcore/util/text/WrappedText.java index cb3aafe..95e8209 100644 --- a/src/main/java/su/nightexpress/nightcore/util/text/WrappedText.java +++ b/src/main/java/su/nightexpress/nightcore/util/text/WrappedText.java @@ -179,7 +179,7 @@ public Builder showText(@NotNull String... text) { } public Builder showItem(@NotNull ItemStack itemStack) { - return this.tag(Tags.HOVER, new ShowItemDecorator(itemStack)); + return this.tag(Tags.HOVER, ShowItemDecorator.from(itemStack)); } public Builder runCommand(@NotNull String value) { diff --git a/src/main/java/su/nightexpress/nightcore/util/text/decoration/ShowItemDecorator.java b/src/main/java/su/nightexpress/nightcore/util/text/decoration/ShowItemDecorator.java index ace5854..9e3499b 100644 --- a/src/main/java/su/nightexpress/nightcore/util/text/decoration/ShowItemDecorator.java +++ b/src/main/java/su/nightexpress/nightcore/util/text/decoration/ShowItemDecorator.java @@ -8,25 +8,48 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; import org.jetbrains.annotations.NotNull; +import su.nightexpress.nightcore.util.BukkitThing; +import su.nightexpress.nightcore.util.ItemNbt; import su.nightexpress.nightcore.util.ItemUtil; public class ShowItemDecorator implements Decorator { - private final ItemStack item; + //private final ItemStack item; + private final String itemData; - public ShowItemDecorator(@NotNull String string) { - this(ItemUtil.decompress(string)); + public static ShowItemDecorator from(@NotNull ItemStack item) { + String content = ItemNbt.compress(item); + return new ShowItemDecorator(content == null ? BukkitThing.toString(item.getType()) : content); + //this.item = item == null ? new ItemStack(Material.AIR) : new ItemStack(item); + //this(ItemUtil.compress(item)); } - public ShowItemDecorator(ItemStack item) { - this.item = item == null ? new ItemStack(Material.AIR) : new ItemStack(item); + public ShowItemDecorator(@NotNull String string) { + //this(ItemUtil.decompress(string)); + this.itemData = string; } @NotNull public HoverEvent createEvent() { - String key = item.getType().getKey().getKey(); - ItemMeta meta = item.getItemMeta(); - Item item = new Item(key, this.item.getAmount(), ItemTag.ofNbt(meta == null ? null : meta.getAsString())); + ItemStack itemStack = null; + + Material material = Material.getMaterial(this.itemData.toUpperCase()); + if (material != null) { + itemStack = new ItemStack(material); + } + else { + try { + itemStack = ItemNbt.decompress(this.itemData); + } + catch (NumberFormatException ignored) { + + } + } + if (itemStack == null) itemStack = new ItemStack(Material.AIR); + + String key = itemStack.getType().getKey().getKey(); + ItemMeta meta = itemStack.getItemMeta(); + Item item = new Item(key, itemStack.getAmount(), ItemTag.ofNbt(meta == null ? null : meta.getAsString())); return new HoverEvent(HoverEvent.Action.SHOW_ITEM, item); } diff --git a/src/main/java/su/nightexpress/nightcore/util/text/tag/Tags.java b/src/main/java/su/nightexpress/nightcore/util/text/tag/Tags.java index 5cdd8a7..82ac952 100644 --- a/src/main/java/su/nightexpress/nightcore/util/text/tag/Tags.java +++ b/src/main/java/su/nightexpress/nightcore/util/text/tag/Tags.java @@ -12,7 +12,7 @@ public class Tags { public static final HoverTag HOVER = new HoverTag(); public static final LineBreakTag LINE_BREAK = new LineBreakTag(); public static final ResetTag RESET = new ResetTag(); - public static final TranslateTag TRANSLATE = new TranslateTag(); + public static final TranslateTag TRANSLATE = new TranslateTag(); public static final FontStyleTag BOLD = new FontStyleTag("b", FontStyleTag.Style.BOLD); public static final FontStyleTag ITALIC = new FontStyleTag("i", FontStyleTag.Style.ITALIC); @@ -21,7 +21,7 @@ public class Tags { public static final FontStyleTag UNDERLINED = new FontStyleTag("u", FontStyleTag.Style.UNDERLINED); public static final ColorTag BLACK = new ColorTag("black", "#000000"); - public static final ColorTag WHITE = new ColorTag("white", "#e8f2f2"); + public static final ColorTag WHITE = new ColorTag("white", "#ffffff"); public static final ColorTag GRAY = new ColorTag("gray", "#aaa8a8"); public static final ColorTag GREEN = new ColorTag("green", "#74ea31"); public static final ColorTag YELLOW = new ColorTag("yellow", "#ead931"); @@ -32,14 +32,14 @@ public class Tags { public static final ColorTag PURPLE = new ColorTag("purple", "#bd31ea"); public static final ColorTag PINK = new ColorTag("pink", "#ea31b2"); - public static final ColorTag DARK_GRAY = new ColorTag("dark_gray", "#6c6c62"); - public static final ColorTag LIGHT_GRAY = new ColorTag("light_gray", "#d4d9d8"); - public static final ColorTag LIGHT_GREEN = new ColorTag("light_green", "#aefd5e"); - public static final ColorTag LIGHT_YELLOW = new ColorTag("light_yellow", "#ffeea2"); - public static final ColorTag LIGHT_ORANGE = new ColorTag("light_orange", "#fdba5e"); - public static final ColorTag LIGHT_RED = new ColorTag("light_red", "#fd5e5e"); - public static final ColorTag LIGHT_BLUE = new ColorTag("light_blue", "#5e9dfd"); - public static final ColorTag LIGHT_CYAN = new ColorTag("light_cyan", "#5edefd"); - public static final ColorTag LIGHT_PURPLE = new ColorTag("light_purple", "#e39fff"); - public static final ColorTag LIGHT_PINK = new ColorTag("light_pink", "#fd8ddb"); + public static final ColorTag DARK_GRAY = new ColorTag("dgray", new String[]{"dark_gray"}, "#6c6c62"); + public static final ColorTag LIGHT_GRAY = new ColorTag("lgray", new String[]{"light_gray"}, "#d4d9d8"); + public static final ColorTag LIGHT_GREEN = new ColorTag("lgreen", new String[]{"light_green"}, "#aefd5e"); + public static final ColorTag LIGHT_YELLOW = new ColorTag("lyellow", new String[]{"light_yellow"}, "#ffeea2"); + public static final ColorTag LIGHT_ORANGE = new ColorTag("lorange", new String[]{"light_orange"}, "#fdba5e"); + public static final ColorTag LIGHT_RED = new ColorTag("lred", new String[]{"light_red"}, "#fd5e5e"); + public static final ColorTag LIGHT_BLUE = new ColorTag("lblue", new String[]{"light_blue"}, "#5e9dfd"); + public static final ColorTag LIGHT_CYAN = new ColorTag("lcyan", new String[]{"light_cyan"}, "#5edefd"); + public static final ColorTag LIGHT_PURPLE = new ColorTag("lpurple", new String[]{"light_purple"}, "#e39fff"); + public static final ColorTag LIGHT_PINK = new ColorTag("lpink", new String[]{"light_pink"}, "#fd8ddb"); } diff --git a/src/main/java/su/nightexpress/nightcore/util/text/tag/api/Tag.java b/src/main/java/su/nightexpress/nightcore/util/text/tag/api/Tag.java index 4edcb9b..37a85a9 100644 --- a/src/main/java/su/nightexpress/nightcore/util/text/tag/api/Tag.java +++ b/src/main/java/su/nightexpress/nightcore/util/text/tag/api/Tag.java @@ -9,9 +9,15 @@ public abstract class Tag { public static final char CLOSE_MARK = '/'; protected final String name; + protected final String[] aliases; public Tag(@NotNull String name) { + this(name, new String[0]); + } + + public Tag(@NotNull String name, @NotNull String[] aliases) { this.name = name.toLowerCase(); + this.aliases = aliases; } @NotNull @@ -24,6 +30,11 @@ public String getName() { return name; } + @NotNull + public String[] getAliases() { + return aliases; + } + @NotNull public String enclose(@NotNull String text) { return this.getFullName() + text + this.getClosingName(); diff --git a/src/main/java/su/nightexpress/nightcore/util/text/tag/impl/ColorTag.java b/src/main/java/su/nightexpress/nightcore/util/text/tag/impl/ColorTag.java index 01d8ac6..174da4f 100644 --- a/src/main/java/su/nightexpress/nightcore/util/text/tag/impl/ColorTag.java +++ b/src/main/java/su/nightexpress/nightcore/util/text/tag/impl/ColorTag.java @@ -13,15 +13,27 @@ public class ColorTag extends Tag implements Decorator { protected final Color color; public ColorTag(@NotNull String name, @NotNull String hex) { - this(name, Color.decode(hex)); + this(name, new String[0], hex); + } + + public ColorTag(@NotNull String name, @NotNull String[] aliases, @NotNull String hex) { + this(name, aliases, Color.decode(hex)); } public ColorTag(@NotNull Color color) { - this(Integer.toHexString(color.getRGB()).substring(2), color); + this(color, new String[0]); + } + + public ColorTag(@NotNull Color color, @NotNull String[] aliases) { + this(Integer.toHexString(color.getRGB()).substring(2), aliases, color); } public ColorTag(@NotNull String name, @NotNull Color color) { - super(name); + this(name, new String[0], color); + } + + public ColorTag(@NotNull String name, @NotNull String[] aliases, @NotNull Color color) { + super(name, aliases); this.color = color; } diff --git a/src/main/java/su/nightexpress/nightcore/util/text/tag/impl/HoverTag.java b/src/main/java/su/nightexpress/nightcore/util/text/tag/impl/HoverTag.java index f5221a0..614de74 100644 --- a/src/main/java/su/nightexpress/nightcore/util/text/tag/impl/HoverTag.java +++ b/src/main/java/su/nightexpress/nightcore/util/text/tag/impl/HoverTag.java @@ -1,11 +1,8 @@ package su.nightexpress.nightcore.util.text.tag.impl; import net.md_5.bungee.api.chat.HoverEvent; -import org.bukkit.Material; -import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import su.nightexpress.nightcore.util.ItemUtil; import su.nightexpress.nightcore.util.StringUtil; import su.nightexpress.nightcore.util.text.decoration.Decorator; import su.nightexpress.nightcore.util.text.decoration.ParsedDecorator; @@ -33,8 +30,12 @@ public boolean isDynamicSize() { @NotNull public String enclose(@NotNull String text, @NotNull String hint) { - String action = HoverEvent.Action.SHOW_TEXT.name().toLowerCase(); - return this.enclose(action, hint, text); + return this.enclose(HoverEvent.Action.SHOW_TEXT, text, hint); + } + + @NotNull + public String enclose(@NotNull HoverEvent.Action action, @NotNull String text, @NotNull String hint) { + return this.enclose(action.name().toLowerCase(), hint, text); } @Override @@ -62,15 +63,15 @@ public ParsedDecorator onParse(@NotNull String sub) { decorator = new ShowTextDecorator(content); } else if (action == HoverEvent.Action.SHOW_ITEM) { - ItemStack item; + /*ItemStack item; Material material = Material.getMaterial(content.toUpperCase()); if (material != null) { item = new ItemStack(material); } - else item = ItemUtil.decompress(content); + else item = ItemUtil.decompress(content);*/ - decorator = new ShowItemDecorator(item); + decorator = new ShowItemDecorator(content); } else return null; diff --git a/src/main/java/su/nightexpress/nightcore/util/text/tag/impl/TranslateTag.java b/src/main/java/su/nightexpress/nightcore/util/text/tag/impl/TranslateTag.java index e14c9cc..24d97d3 100644 --- a/src/main/java/su/nightexpress/nightcore/util/text/tag/impl/TranslateTag.java +++ b/src/main/java/su/nightexpress/nightcore/util/text/tag/impl/TranslateTag.java @@ -12,7 +12,7 @@ public class TranslateTag extends Tag implements Decorator { public static final String NAME = "translate"; public TranslateTag() { - super(NAME); + super(NAME, new String[]{"tr"}); } @Override diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index d1604cf..720f2af 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -3,7 +3,6 @@ main: su.nightexpress.nightcore.NightCore version: '${project.version}' description: Plugin Creation Kit. author: NightExpress -softdepend: [ Vault] api-version: 1.18 load: STARTUP libraries: