YAGL.groovy
package it.fulminazzo.yagl
import groovy.transform.CompileStatic
import it.fulminazzo.yagl.commands.ShellCommand
import it.fulminazzo.yagl.listeners.PersistentListener
import it.fulminazzo.fulmicollection.objects.Refl
import it.fulminazzo.fulmicollection.utils.JarUtils
import it.fulminazzo.yamlparser.utils.FileUtils
import org.bukkit.Bukkit
import org.bukkit.command.Command
import org.bukkit.command.CommandMap
import org.bukkit.plugin.java.JavaPlugin
import org.jetbrains.annotations.NotNull
@CompileStatic
final class YAGL extends JavaPlugin {
private final List<ShellCommand> commands = []
/**
* Loads a resource from the class loader and stores it in the file system.
*
* @param directory the output directory
* @param fileName the name of the resource
* @param resourceDir the name of the directory where the resource is
* @param plugin the fallback plugin in case of a JAR context
*/
static void writeResourceToFile(final @NotNull File directory, final @NotNull String fileName,
final @NotNull String resourceDir, final @NotNull JavaPlugin plugin) {
def file = new File(directory, fileName)
if (file.exists()) FileUtils.deleteFile(file)
FileUtils.createNewFile(file)
def resourceName = "${resourceDir}/${fileName}"
def input = YAGL.getResourceAsStream(resourceName)
if (input == null) input = plugin.getResource(resourceName)
def output = new FileOutputStream(file)
output << input
}
@Override
void onEnable() {
loadCommands()
Bukkit.pluginManager.registerEvents(new PersistentListener(), this)
logger.info("Loaded ${commands.size()} commands")
}
@Override
void onDisable() {
unloadCommands()
}
/**
* Loads all the commands from the <i>{@link #dataFolder}/commands</i> directory.
* If it does not exist, it is created using {@link #saveDefaultCommands(File)}.
*/
void loadCommands() {
this.commands.clear()
File commandsDir = new File(dataFolder, 'commands')
if (!commandsDir.exists()) saveDefaultCommands(commandsDir)
File[] files = commandsDir.listFiles()
if (files != null)
this.commands.addAll(files.findAll { it.name.endsWith('.groovy') }.collect { new ShellCommand(it) })
commandMap().ifPresent { map -> this.commands.each { map.register(name, it) } }
}
/**
* Unloads all the commands loaded in {@link #commands}.
*/
void unloadCommands() {
commandMap().ifPresent(map -> {
Map<String, Command> commands = new Refl<>(map).getFieldObject('knownCommands')
if (commands == null) logger.warning('Could not find \'knownCommands\' field in CommandMap')
else commands.keySet().collect().each { key ->
Command value = commands.get(key)
if (this.commands.contains(value)) commands.remove(key, value)
}
})
}
/**
* Saves all the default command scripts to the given directory
*
* @param commandsDir the output directory
*/
void saveDefaultCommands(final @NotNull File commandsDir) {
final resourceDir = '/commands'
FileUtils.createFolder(commandsDir)
getClass().getResourceAsStream(resourceDir).withReader { reader ->
String fileName
while ((fileName = reader.readLine()) != null) writeResourceToFile(commandsDir, fileName, resourceDir, this)
}
Iterator<String> jarEntries = JarUtils.getEntries(YAGL, '')
while (jarEntries.hasNext()) {
def entry = jarEntries.next()
if (entry.startsWith(resourceDir.substring(1)) && entry.length() > resourceDir.length())
writeResourceToFile(commandsDir, entry.substring(resourceDir.length()), resourceDir, this)
}
}
private static Optional<CommandMap> commandMap() {
def pluginManager = Bukkit.pluginManager
// Terrible line, but necessary for JaCoCo coverage report to 100%
pluginManager == null ? Optional.empty() : Optional.ofNullable((CommandMap) new Refl<>(pluginManager)
.getFieldObject('commandMap'))
}
}