diff --git a/core/src/main/java/de/erethon/dungeonsxl/DungeonsXL.java b/core/src/main/java/de/erethon/dungeonsxl/DungeonsXL.java index 3c8d2473..4759b386 100644 --- a/core/src/main/java/de/erethon/dungeonsxl/DungeonsXL.java +++ b/core/src/main/java/de/erethon/dungeonsxl/DungeonsXL.java @@ -116,6 +116,7 @@ public class DungeonsXL extends DREPlugin implements DungeonsAPI { public static final File LOOT_TABLES = new File(SCRIPTS, "loottables"); public static final File MOBS = new File(SCRIPTS, "mobs"); public static final File SIGNS = new File(SCRIPTS, "signs"); + public static final File COMMANDS = new File(SCRIPTS, "commands"); public static final Map> LEGACY_SIGNS = new HashMap<>(); static { @@ -185,6 +186,7 @@ public class DungeonsXL extends DREPlugin implements DungeonsAPI { private GlobalProtectionCache protections; private AnnouncerCache announcers; private Registry signScriptRegistry; + private Registry commandScriptRegistry; public DungeonsXL() { settings = DREPluginSettings.builder() @@ -236,6 +238,7 @@ public class DungeonsXL extends DREPlugin implements DungeonsAPI { LOOT_TABLES.mkdir(); MOBS.mkdir(); SIGNS.mkdir(); + COMMANDS.mkdir(); } public void loadConfig() { @@ -258,6 +261,7 @@ public class DungeonsXL extends DREPlugin implements DungeonsAPI { protections = new GlobalProtectionCache(this); announcers = new AnnouncerCache(this); signScriptRegistry = new Registry<>(); + commandScriptRegistry = new Registry<>(); dCommands = new DCommandCache(this); } @@ -389,6 +393,11 @@ public class DungeonsXL extends DREPlugin implements DungeonsAPI { signScriptRegistry.add(sign.getName(), sign); } + for (File script : FileUtil.getFilesForFolder(COMMANDS)) { + CommandScript cmd = new CommandScript(script); + commandScriptRegistry.add(cmd.getName(), cmd); + } + dCommands.register(this); loaded = true; } @@ -595,6 +604,15 @@ public class DungeonsXL extends DREPlugin implements DungeonsAPI { return signScriptRegistry; } + /** + * Returns a registry of the loaded command scripts. + * + * @return a registry of the loaded command scripts + */ + public Registry getCommandScriptRegistry() { + return commandScriptRegistry; + } + @Deprecated private Set guis = new HashSet<>(); diff --git a/core/src/main/java/de/erethon/dungeonsxl/sign/windup/CommandScript.java b/core/src/main/java/de/erethon/dungeonsxl/sign/windup/CommandScript.java new file mode 100644 index 00000000..cd1418f3 --- /dev/null +++ b/core/src/main/java/de/erethon/dungeonsxl/sign/windup/CommandScript.java @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2012-2020 Frank Baumann + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package de.erethon.dungeonsxl.sign.windup; + +import de.erethon.dungeonsxl.DungeonsXL; +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import org.bukkit.command.CommandSender; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.entity.Player; +import org.bukkit.permissions.Permission; + +/** + * @author Daniel Saukel + */ +public class CommandScript { + + private String name; + private File file; + private List commands = new ArrayList<>(); + private Permission permission; + + public CommandScript(String name, List commands, Permission permission) { + this.name = name; + file = new File(DungeonsXL.COMMANDS, name + ".yml"); + + setCommands(commands); + + if (permission != null) { + setPermission(permission); + } else { + setPermission(new Permission("dxl.cmd." + name)); + } + } + + public CommandScript(File file) { + FileConfiguration config = YamlConfiguration.loadConfiguration(file); + + name = file.getName().replace(".yml", ""); + this.file = file; + + if (config.getStringList("commands") != null) { + setCommands(config.getStringList("commands")); + } + if (config.getString("permission") != null) { + setPermission(new Permission(config.getString("permission"))); + } else { + setPermission(new Permission("dxl.cmd." + name)); + } + } + + public String getName() { + return name; + } + + public File getFile() { + return file; + } + + public List getCommands() { + return commands; + } + + public void setCommands(List commands) { + this.commands = commands; + } + + public Permission getPermission() { + return permission; + } + + public Permission getPermission(CommandSender sender) { + if (!(sender instanceof Player)) { + return new Permission(getPermission() + ".asconsole"); + + } else if (sender.isOp()) { + return new Permission(getPermission() + ".asop"); + + } else { + return permission; + } + } + + public void setPermission(Permission permission) { + this.permission = permission; + } + +} diff --git a/core/src/main/java/de/erethon/dungeonsxl/sign/windup/CommandSign.java b/core/src/main/java/de/erethon/dungeonsxl/sign/windup/CommandSign.java new file mode 100644 index 00000000..3e7b4641 --- /dev/null +++ b/core/src/main/java/de/erethon/dungeonsxl/sign/windup/CommandSign.java @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2012-2020 Frank Baumann + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package de.erethon.dungeonsxl.sign.windup; + +import de.erethon.commons.misc.EnumUtil; +import de.erethon.commons.misc.NumberUtil; +import de.erethon.dungeonsxl.DungeonsXL; +import de.erethon.dungeonsxl.api.DungeonsAPI; +import de.erethon.dungeonsxl.api.sign.Windup; +import de.erethon.dungeonsxl.api.world.InstanceWorld; +import de.erethon.dungeonsxl.player.DPermission; +import de.erethon.dungeonsxl.trigger.InteractTrigger; +import de.erethon.dungeonsxl.world.DGameWorld; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.block.Sign; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +/** + * @author Daniel Saukel + */ +public class CommandSign extends Windup { + + private enum Executor { + DEFAULT, + OP, + CONSOLE + } + + private CommandScript script; + private Executor executor; + + public CommandSign(DungeonsAPI api, Sign sign, String[] lines, InstanceWorld instance) { + super(api, sign, lines, instance); + } + + public CommandScript getScript() { + return script; + } + + @Override + public String getName() { + return "CMD"; + } + + @Override + public String getBuildPermission() { + return DPermission.SIGN.getNode() + ".cmd"; + } + + @Override + public boolean isOnDungeonInit() { + return false; + } + + @Override + public boolean isProtected() { + return false; + } + + @Override + public boolean isSetToAir() { + return true; + } + + @Override + public boolean validate() { + script = ((DungeonsXL) api).getCommandScriptRegistry().get(getLine(1)); + return script != null; + } + + @Override + public void initialize() { + String[] attributes = getLine(2).split(","); + + if (attributes.length == 3) { + delay = NumberUtil.parseDouble(attributes[0]); + interval = NumberUtil.parseDouble(attributes[1]); + executor = EnumUtil.getEnumIgnoreCase(Executor.class, attributes[2]); + if (executor == null) { + executor = Executor.DEFAULT; + } + + } else if (attributes.length == 2) { + delay = NumberUtil.parseDouble(attributes[0]); + double interval = NumberUtil.parseDouble(attributes[1], -1); + if (interval == -1) { + executor = EnumUtil.getEnumIgnoreCase(Executor.class, attributes[1]); + } else { + this.interval = interval; + } + if (executor == null) { + executor = Executor.DEFAULT; + } + + } else if (attributes.length == 1) { + double delay = NumberUtil.parseDouble(attributes[0], -1); + if (delay == -1) { + executor = EnumUtil.getEnumIgnoreCase(Executor.class, attributes[0]); + } else { + this.delay = delay; + } + + } else if (attributes.length == 0) { + executor = Executor.DEFAULT; + } + + setRunnable(new CommandTask(this, Bukkit.getPluginManager().isPluginEnabled("PlaceholderAPI"))); + + if (!getTriggers().isEmpty()) { + setToAir(); + return; + } + + InteractTrigger trigger = InteractTrigger.getOrCreate(0, getSign().getBlock(), (DGameWorld) getGameWorld()); + if (trigger != null) { + trigger.addListener(this); + getTriggers().add(trigger); + } + + getSign().setLine(0, ChatColor.DARK_BLUE + "############"); + getSign().setLine(1, ChatColor.GREEN + script.getName()); + getSign().setLine(2, ""); + getSign().setLine(3, ChatColor.DARK_BLUE + "############"); + getSign().update(); + } + + @Override + public void activate() { + if (executor == Executor.CONSOLE) { + ((CommandTask) getRunnable()).setSender(Bukkit.getConsoleSender(), false); + startTask(); + active = true; + } else { + markAsErroneous("Sign is set to be performed by a player but is triggered by a trigger that cannot be attributed to a player (e.g. mob)"); + } + } + + @Override + public boolean activate(Player player) { + CommandSender sender = player; + boolean wasOp = player.isOp(); + if (executor == Executor.OP) { + player.setOp(true); + } else if (executor == Executor.CONSOLE) { + sender = Bukkit.getConsoleSender(); + } + ((CommandTask) getRunnable()).setSender(sender, wasOp); + startTask(); + active = true; + return true; + } + +} diff --git a/core/src/main/java/de/erethon/dungeonsxl/sign/windup/CommandTask.java b/core/src/main/java/de/erethon/dungeonsxl/sign/windup/CommandTask.java new file mode 100644 index 00000000..ee37bf4d --- /dev/null +++ b/core/src/main/java/de/erethon/dungeonsxl/sign/windup/CommandTask.java @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2012-2020 Frank Baumann + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package de.erethon.dungeonsxl.sign.windup; + +import me.clip.placeholderapi.PlaceholderAPI; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; + +/** + * @author Daniel Saukel + */ +public class CommandTask extends BukkitRunnable { + + private Player player; + private boolean wasOp; + private CommandSign sign; + private CommandScript script; + private CommandSender sender; + private boolean papi; + + private int k; + + public CommandTask(CommandSign sign, boolean papi) { + this.sign = sign; + this.script = sign.getScript(); + this.papi = papi; + } + + public void setSender(CommandSender sender, boolean wasOp) { + this.sender = sender; + this.wasOp = wasOp; + } + + @Override + public void run() { + if (!player.hasPermission(script.getPermission(player))) { + player.sendMessage(ChatColor.RED + "You do not have permission to use this command."); + return; + } + + String command = script.getCommands().get(k++).replace("%player%", sender.getName()).replace("%player_name%", sender.getName()); + if (papi) { + Bukkit.getServer().dispatchCommand(sender, PlaceholderAPI.setPlaceholders(player, command)); + } else { + Bukkit.getServer().dispatchCommand(sender, command); + } + + if (k >= script.getCommands().size()) { + sign.deactivate(); + } + } + + @Override + public void cancel() { + super.cancel(); + if (sender != Bukkit.getConsoleSender()) { + sender.setOp(wasOp); + } + } + +}