diff --git a/README.md b/README.md index 3e21536..1cdc552 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ # AdvancementCommand Runs a command, optionally as console or permission elevated when receiving advancements + ## Downloads See [Releases](https://github.com/aikar/AdvancementCommand/releases) @@ -8,7 +9,7 @@ See examples below for format Each entry must define: - advancement - - command OR alias + - command OR commands OR alias An advancement can be defined multiple times in the list to perform multiple commands. @@ -17,8 +18,9 @@ If no other configuration is provided, it will be ran as the player without op o Alias will alias one advancement to run the same commands as another, so you don't have to duplicate it. ### Keys - - **advancement**: the advancement key such as `minecraft:brewed_potion` to trigger on + - **advancement**: the advancement key such as `minecraft:husbandry/root` to trigger on - **command**: what command to run, see variables below for template variables + - **commands**: Alternatively, a list of what command to run, see variables below for template variables - **run_as**: `player` or `console` - who receives the command feedback - **op**: Should player be given temporary op for this command. Unnecessary for `run_as: console` - **permission**: Permission node to give temporarily for this command. Example: @@ -38,7 +40,7 @@ Inside of a command, you may use the following variables - **%PLAYER**: The name of the player earning the advancement. - **%UUID**: The UUID of the player earning the advancement. - **%PLAYERDISPLAYNAME**: The display name of the player earning the advancement. (might be the same as player) - - **%ADVANCEMENT**: The advancement key (eg `minecraft:brewed_potion`) being earned. + - **%ADVANCEMENT**: The advancement key (eg `minecraft:adventure/root`) being earned. ## Examples ```yaml @@ -51,7 +53,9 @@ on_advancement: # run a standard command with no permissions - advancement: minecraft:example run_as: player - command: say Hey I just got an advancement! + commands: + - say Hey I just got an advancement! + - me Dances! op: false # run a command as the console (command feedback to console instead of the player, ideal for rank changes) - advancement: myplugin:gainrank1 @@ -63,15 +67,27 @@ on_advancement: run_as: player command: teleport %player some secret coords permission: minecraft.command.teleport - - advancement: minecraft:brew_potion + - advancement: minecraft:husbandry/tame_an_animal alias: myplugin:teleport_to_secret - - advancement: minecraft:bred_animals + - advancement: minecraft:husbandry/plant_seed alias: myplugin:teleport_to_secret ``` ## Tricks You may define fake advancement keys, to define a list of actions, and then use them -inside of your alias targets +inside of your alias targets. + +## Contributing +See Issues section. + +Join [#aikar on Spigot IRC - irc.spi.gt](https://aikarchat.emc.gs) to discuss. + +Or [Code With Aikar](https://aikardiscord.emc.gs) Discord. + +## Other projects by Aikar / Empire Minecraft + - [ACF - Annotation Command Framework](https://acf.emc.gs) - The most powerful command framework for Bukkit, Sponge, BungeeCoord, JDA and any other platform. Build rich command definitions powered by annotations. + - [TaskChain](https://taskchain.emc.gs) - Powerful context control to dispatch tasks Async, then access the result sync for API usage. Concurrency controls too. + - [Minecraft Timings](https://github.com/aikar/minecraft-timings/) - Add Timings to your plugin in a safe way that works on all Bukkit platforms (CraftBukkit - no timings, Spigot - Timings v1, Paper and Paper forks - Timings v2) ## License As with all my other public projects diff --git a/pom.xml b/pom.xml index d928510..edc1848 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ co.aikar advancementcommand - 1.0.0 + 1.1.0 jar AdvancementCommand diff --git a/src/main/java/co/aikar/advancementcommand/AdvancementCommand.java b/src/main/java/co/aikar/advancementcommand/AdvancementCommand.java index da4c2cb..db7fc9f 100644 --- a/src/main/java/co/aikar/advancementcommand/AdvancementCommand.java +++ b/src/main/java/co/aikar/advancementcommand/AdvancementCommand.java @@ -1,6 +1,7 @@ package co.aikar.advancementcommand; import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.ListMultimap; import org.bukkit.Bukkit; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; @@ -23,11 +24,12 @@ @SuppressWarnings("unused") public final class AdvancementCommand extends JavaPlugin implements Listener { - private final ArrayListMultimap commandMap = ArrayListMultimap.create(); + private final ListMultimap commandMap = ArrayListMultimap.create(); private static final Pattern PLAYER = Pattern.compile("%player\b", Pattern.CASE_INSENSITIVE); private static final Pattern PLAYER_DISPLAY = Pattern.compile("%playerdisplayname\b", Pattern.CASE_INSENSITIVE); private static final Pattern UUID = Pattern.compile("%uuid\b", Pattern.CASE_INSENSITIVE); private static final Pattern ADVANCEMENT = Pattern.compile("%advancement\b", Pattern.CASE_INSENSITIVE); + @Override public void onEnable() { getServer().getPluginManager().registerEvents(this, this); @@ -67,39 +69,37 @@ public void reloadConfig() { @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) public void onPlayerAdvancementDone(PlayerAdvancementDoneEvent event) { String key = event.getAdvancement().getKey().toString(); - runCommands(event, key); + processAdvancement(event, key); } - private void runCommands(PlayerAdvancementDoneEvent event, String key) { + private void processAdvancement(PlayerAdvancementDoneEvent event, String key) { List commands = this.commandMap.get(key.toLowerCase()); if (commands == null || commands.isEmpty()) { return; } + Player player = event.getPlayer(); for (CommandInfo info : commands) { if (info.alias != null) { - doWithPermissions(info, event.getPlayer(), () -> runCommands(event, info.alias)); + doWithPermissions(info, player, () -> processAdvancement(event, info.alias)); } else { - runCommand(event, key, info); + doWithPermissions(info, player, () -> dispatchCommands(event, key, info)); } } } - private void runCommand(PlayerAdvancementDoneEvent event, String key, CommandInfo info) { + private Player dispatchCommands(PlayerAdvancementDoneEvent event, String key, CommandInfo info) { Player player = event.getPlayer(); + CommandSender sender = info.asPlayer ? player : Bukkit.getConsoleSender(); String name = player.getName(); String displayName = player.getDisplayName(); - String command = PLAYER.matcher(info.command).replaceAll(name); - command = PLAYER_DISPLAY.matcher(command).replaceAll(displayName); - command = ADVANCEMENT.matcher(command).replaceAll(key); - command = UUID.matcher(command).replaceAll(player.getUniqueId().toString()); - - if (!(info.asPlayer)) { - Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(), command); - return; + for (String command : info.commands) { + command = PLAYER.matcher(command).replaceAll(name); + command = PLAYER_DISPLAY.matcher(command).replaceAll(displayName); + command = ADVANCEMENT.matcher(command).replaceAll(key); + command = UUID.matcher(command).replaceAll(player.getUniqueId().toString()); + Bukkit.getServer().dispatchCommand(sender, command); } - - String finalCommand = command; - doWithPermissions(info, player, () -> Bukkit.getServer().dispatchCommand(player, finalCommand)); + return player; } private void doWithPermissions(CommandInfo info, Player player, Runnable run) { @@ -132,22 +132,26 @@ public boolean onCommand(CommandSender sender, Command command, String label, St return true; } - private class CommandInfo { + private static class CommandInfo { final boolean asPlayer; - final String command; + final List commands = new ArrayList<>(); final String alias; final boolean op; final List permissions = new ArrayList<>(); CommandInfo(ConfigurationSection section) { - this.asPlayer = !section.getString("run_as", "player").equals("console"); - this.command = section.getString("command"); + this.asPlayer = !section.getString("run_as", "player").trim().equalsIgnoreCase("console"); + String command = section.getString("command"); + if (command != null) { + this.commands.add(command); + } + this.commands.addAll(section.getStringList("commands")); this.alias = section.getString("alias"); - boolean commandEmpty = this.command == null || this.command.isEmpty(); + boolean commandEmpty = this.commands.isEmpty(); if (this.alias != null && commandEmpty) { - throw new Error("command can not be empty"); + throw new IllegalArgumentException("Commands can not be empty"); } if (!commandEmpty && this.alias != null) { - throw new Error("You can not have both a command and alias configuration"); + throw new IllegalArgumentException("You can not have both a command and alias configuration"); } this.op = section.getBoolean("op", false); String permission = section.getString("permission"); @@ -155,9 +159,7 @@ private class CommandInfo { this.permissions.add(permission); } List permissions = section.getStringList("permissions"); - if (permissions != null) { - this.permissions.addAll(permissions); - } + this.permissions.addAll(permissions); } } } diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index cab06d3..bccf1cd 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -2,5 +2,16 @@ name: AdvancementCommand version: ${project.version} main: co.aikar.advancementcommand.AdvancementCommand authors: [Aikar] -description: When an advancement is ran, run a command at potentially elevated permissions -website: https://aikar.co +description: When an advancement is ran, run commands at potentially elevated permissions +website: https://github.com/aikar/AdvancementCommand + +comands: + advancementcommand: + description: Reloads AdvancementCommand config + aliases: [advcom] + permission: advancementcommand + +permissions: + advancementcommand: + description: Lets you reload AdvancementCommand config + default: op