/* * Copyright or © or Copr. Amaury Carrade (2014 - 2016) * * http://amaury.carrade.eu * * This software is governed by the CeCILL-B license under French law and * abiding by the rules of distribution of free software. You can use, * modify and/ or redistribute the software under the terms of the CeCILL-B * license as circulated by CEA, CNRS and INRIA at the following URL * "http://www.cecill.info". * * As a counterpart to the access to the source code and rights to copy, * modify and redistribute granted by the license, users are provided only * with a limited warranty and the software's author, the holder of the * economic rights, and the successive licensors have only limited * liability. * * In this respect, the user's attention is drawn to the risks associated * with loading, using, modifying and/or developing or reproducing the * software by the user in light of its specific status of free software, * that may mean that it is complicated to manipulate, and that also * therefore means that it is reserved for developers and experienced * professionals having in-depth computer knowledge. Users are therefore * encouraged to load and test the software's suitability as regards their * requirements in conditions enabling the security of their systems and/or * data to be ensured and, more generally, to use and operate it in the * same conditions as regards security. * * The fact that you are presently reading this means that you have had * knowledge of the CeCILL-B license and that you accept its terms. */ package eu.carrade.amaury.UHCReloaded.misc; import eu.carrade.amaury.UHCReloaded.UHCReloaded; import eu.carrade.amaury.UHCReloaded.task.ScheduledCommandsExecutorTask; import eu.carrade.amaury.UHCReloaded.utils.UHUtils; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; /** * This will execute the commands to be executed during runtime, as configured in the config.yml file * or added through the API. */ public class RuntimeCommandsExecutor { private UHCReloaded p = null; /** * Stores the commands to be executed later. * <p> * The first map (String->HashMap) associates a key to a group of commands launched at the same time.<br> * The sub-map (Integer->HashSet) associates a delay, in seconds, with a set containing the commands to be * executed this number of seconds after the call of the {@link #registerCommandsInScheduler(String)} * method. */ private Map<String, HashMap<Integer, HashSet<String>>> scheduled = new HashMap<>(); /** * The key for the commands executed when the server starts. */ public final static String AFTER_SERVER_START = "internal.server-start"; /** * The key for the commands executed after the beginning of the game. */ public final static String AFTER_GAME_START = "internal.game-start"; /** * The key for the commands executed after the end of the game. */ public final static String AFTER_GAME_END = "internal.game-end"; public RuntimeCommandsExecutor(UHCReloaded plugin) { p = plugin; importFromConfig("commands.execute-server-start", AFTER_SERVER_START); importFromConfig("commands.execute-start", AFTER_GAME_START); importFromConfig("commands.execute-end", AFTER_GAME_END); } /** * Register the commands registered under the given key in the Bukkit' scheduler. * <p> * Delays are from the execution of this method. * * @param key The key to schedule. All commands previously registered under this key will be executed. */ public void registerCommandsInScheduler(String key) { registerCommandsInScheduler(scheduled.get(key)); } /** * Register the given commands in the Bukkit' scheduler. * * Delays are from the execution of this method. * @param scheduledCommands */ private void registerCommandsInScheduler(Map<Integer, HashSet<String>> scheduledCommands) { if (scheduledCommands != null) { for (Entry<Integer, HashSet<String>> scheduledCommandsStack : scheduledCommands.entrySet()) { p.getServer().getScheduler().runTaskLater( p, new ScheduledCommandsExecutorTask(p, scheduledCommandsStack.getValue()), scheduledCommandsStack.getKey() * 20l ); } } } /** * Schedules a command. * <p> * To schedule a command executed by the plugin, like in the configuration file, you will have * to use the keys defined as static attributes of this class: * {@link #AFTER_SERVER_START}, {@link #AFTER_GAME_END} and {@link #AFTER_GAME_START}. * * @param key The command will be stored under this key. * The keys internally used by the plugin start by "{@code internal.}". * @param command The command to add. * @param delay The delay (seconds). */ public void scheduleCommand(String key, String command, Integer delay) { if (!scheduled.containsKey(key)) { scheduled.put(key, new HashMap<Integer, HashSet<String>>()); } scheduleCommand(scheduled.get(key), command, delay); } /** * Schedules a command. * * @param scheduledCommands A map containing the scheduled commands, sorted by delay. * @param command The command to add. * @param delay The delay (seconds). */ private void scheduleCommand(Map<Integer, HashSet<String>> scheduledCommands, String command, Integer delay) { HashSet<String> list = scheduledCommands.get(delay); if (list == null) { list = new HashSet<>(); scheduledCommands.put(delay, list); } list.add(clearCommandName(command)); } /** * Removes the given command from everywhere. * * @param key The command will be stored under this key. * The keys internally used by the plugin start by "{@code internal.}". * @param command The command. Not case-sensitive. */ public void removeScheduledCommand(String key, String command) { removeScheduledCommand(scheduled.get(key), command); } /** * Removes the given command from everywhere. * * @param scheduledCommands A map containing the scheduled commands, sorted by delay. * @param command The command. Not case-sensitive. */ private void removeScheduledCommand(Map<Integer, HashSet<String>> scheduledCommands, String command) { for (HashSet<String> commands : scheduledCommands.values()) { for (String scheduledCommand : new HashSet<String>(commands)) { if (scheduledCommand.equalsIgnoreCase(clearCommandName(command))) { commands.remove(scheduledCommand); } } } } /** * Removes the given command from everywhere. * * @param key The command will be stored under this key. * The keys internally used by the plugin start by "{@code internal.}". * @param command The command. Not case-sensitive. */ public void removeScheduledCommand(String key, String command, Integer delay) { removeScheduledCommand(scheduled.get(key), command, delay); } /** * Removes the given command from everywhere. * * @param scheduledCommands A map containing the scheduled commands, sorted by delay. * @param command The command. Not case-sensitive. */ private void removeScheduledCommand(Map<Integer, HashSet<String>> scheduledCommands, String command, Integer delay) { HashSet<String> commands = scheduledCommands.get(delay); if (commands != null) { for (String scheduledCommand : commands) { if (scheduledCommand.equalsIgnoreCase(clearCommandName(command))) { commands.remove(scheduledCommand); } } } } /* Utilities */ /** * Imports the commands stored in the configuration. * * @param path The path in the config file. * @param key The command will be stored under this key. * The keys internally used by the plugin start by "{@code internal.}". */ private void importFromConfig(String path, String key) { List<Map<?, ?>> rawCommands = p.getConfig().getMapList(path); if (rawCommands != null) { for (Map<?, ?> rawCommand : rawCommands) { String cmd = String.valueOf(rawCommand.get("exec")); Integer delay; if (cmd == null || cmd.isEmpty()) continue; try { delay = UHUtils.string2Time(String.valueOf(rawCommand.get("delay"))); } catch (IllegalArgumentException e) { delay = 0; } scheduleCommand(key, cmd, delay); } } } private String clearCommandName(String command) { if (command.startsWith("/")) { command = command.substring(1); } return command; } }