/* * This file is part of NucleusFramework for Bukkit, licensed under the MIT License (MIT). * * Copyright (c) JCThePants (www.jcwhatever.com) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package com.jcwhatever.nucleus; import com.jcwhatever.nucleus.managed.commands.ICommand; import com.jcwhatever.nucleus.managed.commands.ICommandDispatcher; import com.jcwhatever.nucleus.managed.language.ILanguageContext; import com.jcwhatever.nucleus.managed.messaging.IChatPrefixed; import com.jcwhatever.nucleus.managed.messaging.IMessenger; import com.jcwhatever.nucleus.mixins.ILoadable; import com.jcwhatever.nucleus.providers.storage.DataStorage; import com.jcwhatever.nucleus.storage.DataPath; import com.jcwhatever.nucleus.storage.IDataNode; import com.jcwhatever.nucleus.storage.MemoryDataNode; import org.bukkit.command.PluginCommand; import org.bukkit.event.Listener; import org.bukkit.plugin.PluginDescriptionFile; import org.bukkit.plugin.PluginManager; import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPluginLoader; import java.io.File; import java.util.ArrayList; import java.util.List; import java.util.Map; /** * An abstract implementation of a Bukkit plugin with * NucleusFramework specific features. */ public abstract class NucleusPlugin extends JavaPlugin implements IChatPrefixed, ILoadable { static List<NucleusPlugin> _enabled = new ArrayList<>(10); private ILanguageContext _languageContext; private ICommandDispatcher _commandDispatcher; private IDataNode _dataNode; private boolean _isDebugging; private IMessenger _messenger; private IMessenger _anonMessenger; private boolean _isTesting; boolean _isEnabled; /** * Constructor. */ public NucleusPlugin() { super(); try { onInit(); } catch (Throwable e) { e.printStackTrace(); throw new RuntimeException(e); } } /** * Constructor for testing. */ protected NucleusPlugin(JavaPluginLoader loader, PluginDescriptionFile description, File dataFolder, File file) { super(loader, description, dataFolder, file); _isTesting = true; try { onInit(); } catch (Throwable e) { e.printStackTrace(); throw new RuntimeException(e); } } /** * Determine if the plugin is in debug mode. */ public final boolean isDebugging() { return _isDebugging; } /** * Determine if the plugin is being tested. */ public final boolean isTesting() { return _isTesting; } /** * Set the plugins debug mode. * * @param isDebugging True to turn debug on. */ public final void setDebugging(boolean isDebugging) { _isDebugging = isDebugging; } /** * Determine if the plugin is finished loading. */ @Override public boolean isLoaded() { return isEnabled() && _isEnabled; } @Override public abstract String getChatPrefix(); @Override public abstract String getConsolePrefix(); /** * Get the plugins data node. */ public IDataNode getDataNode() { return _dataNode; } /** * Get the plugins language context. */ public ILanguageContext getLanguageContext() { return _languageContext; } /** * Get the plugins chat and console messenger. */ public IMessenger getMessenger() { return _messenger; } /** * Get the plugins anonymous chat messenger. * * <p>A messenger that has no chat prefix.</p> */ public IMessenger getAnonMessenger() { return _anonMessenger; } /** * Get the plugins command dispatcher. */ public ICommandDispatcher getCommandDispatcher() { return _commandDispatcher; } @Override public final void onEnable() { onPreEnable(); _messenger = Nucleus.getMessengerFactory().get(this); _anonMessenger = Nucleus.getMessengerFactory().getAnon(this); loadDataNode(); _languageContext = Nucleus.getLanguageManager().createContext(this); Nucleus.registerPlugin(this); if (!(this instanceof BukkitPlugin)) _enabled.add(this); onPostPreEnable(); _commandDispatcher = Nucleus.getCommandManager().createDispatcher(this); Map<String, Map<String, Object>> commands = getDescription().getCommands(); if (commands != null) { for (String cmd : commands.keySet()) { PluginCommand command = getCommand(cmd); command.setExecutor(_commandDispatcher); command.setTabCompleter(_commandDispatcher); } } } @Override public final void onDisable() { Nucleus.unregisterPlugin(this); try { onDisablePlugin(); } catch (Throwable e) { e.printStackTrace(); } } /** * Invoked when the plugin is instantiated. * * <p>Intended for optional override.</p> */ protected void onInit() { // do nothing } /** * Invoked before the plugin config is loaded. * * <p>Intended for optional override.</p> */ protected void onPreEnable() { // do nothing } /** * Invoked after the plugin data node is loaded but before the plugin is enabled. * * <p>Intended for optional override.</p> */ protected void onPostPreEnable() { // do nothing } /** * Invoked when the plugin is enabled. */ protected abstract void onEnablePlugin(); /** * Invoked when the plugin is disabled. */ protected abstract void onDisablePlugin(); /** * Register a command. */ protected void registerCommand(Class<? extends ICommand> commandClass) { _commandDispatcher.registerCommand(commandClass); } /** * Register event listeners. * * @param listeners The listeners to register. */ protected void registerEventListeners(Listener...listeners) { PluginManager pm = getServer().getPluginManager(); for (Listener listener : listeners) { pm.registerEvents(listener, this); } } /* * Load the plugins data node. */ private void loadDataNode() { File dir = getDataFolder(); if (!_isTesting && !dir.exists() && !dir.mkdirs()) { throw new RuntimeException("Failed to create data folders."); } if (_isTesting) { _dataNode = new MemoryDataNode(this); } else { _dataNode = DataStorage.get(this, new DataPath("config")); if (!_dataNode.load()) { getServer().getPluginManager().disablePlugin(this); throw new RuntimeException("The plugins data node (config) could not be loaded!"); } } _isDebugging = _dataNode.getBoolean("debug"); } }