Package com.bergerkiller.bukkit.common

Source Code of com.bergerkiller.bukkit.common.PluginBase

package com.bergerkiller.bukkit.common;

import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.logging.Level;

import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.PluginCommand;
import org.bukkit.entity.Player;
import org.bukkit.event.Listener;
import org.bukkit.permissions.Permission;
import org.bukkit.permissions.PermissionDefault;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.JavaPlugin;

import com.bergerkiller.bukkit.common.config.BasicConfiguration;
import com.bergerkiller.bukkit.common.config.ConfigurationNode;
import com.bergerkiller.bukkit.common.config.FileConfiguration;
import com.bergerkiller.bukkit.common.internal.CommonPlugin;
import com.bergerkiller.bukkit.common.localization.ILocalizationDefault;
import com.bergerkiller.bukkit.common.metrics.Metrics;
import com.bergerkiller.bukkit.common.permissions.IPermissionDefault;
import com.bergerkiller.bukkit.common.permissions.NoPermissionException;
import com.bergerkiller.bukkit.common.protocol.PacketListener;
import com.bergerkiller.bukkit.common.protocol.PacketMonitor;
import com.bergerkiller.bukkit.common.protocol.PacketType;
import com.bergerkiller.bukkit.common.reflection.classes.PluginDescriptionFileRef;
import com.bergerkiller.bukkit.common.utils.CommonUtil;
import com.bergerkiller.bukkit.common.utils.LogicUtil;
import com.bergerkiller.bukkit.common.utils.MathUtil;
import com.bergerkiller.bukkit.common.utils.PacketUtil;
import com.bergerkiller.bukkit.common.utils.ParseUtil;
import com.bergerkiller.bukkit.common.utils.StringUtil;

/**
* The extended javaPlugin base used to communicate with BKCommonLib<br><br>
*
* Handles dependencies, command registration, event listener registration,
* permissions and permission defaults, logging, error handling and localization.
*/
public abstract class PluginBase extends JavaPlugin {
  private String disableMessage, enableMessage;
  private FileConfiguration permissionconfig, localizationconfig;
  private final BasicConfiguration pluginYaml = new BasicConfiguration();
  private boolean enabled = false;
  private boolean wasDisableRequested = false;
  private Metrics metrics;

  /**
   * Gets the logger for a specific module in this Plugin
   *
   * @param modulePath for the module
   * @return a new Module Logger
   */
  public ModuleLogger getModuleLogger(String... modulePath) {
    return new ModuleLogger(this, modulePath);
  }

  /**
   * Logs a message to the server console
   *
   * @param level of the message
   * @param message to log
   */
  public void log(Level level, String message) {
    this.getLogger().log(level, message);
  }

  /**
   * Logs the action of a certain player
   *
   * @param by whome the action was performed (only logged if it is a player)
   * @param action the player performed
   */
  public void logAction(CommandSender by, String action) {
    if (by instanceof Player) {
      log(Level.INFO, ((Player) by).getName() + " " + action);
    }
  }

  /**
   * Gets the version of this Plugin
   *
   * @return Plugin version
   */
  public final String getVersion() {
    return this.getDescription().getVersion();
  }

  /**
   * Gets the version of this Plugin parsed into a major-minor number.
   * This expects the version of the plugin to be formatted like <b>MAJOR.MINOR.REVISION.BUILD</b>
   * with separate parts not exceeding 100.<br>
   * <b>REVISION and BUILD will not be contained in this version number!</b><br><br>
   *
   * Examples:<br>
   * - v1.0 = 100<br>
   * - v8.6 = 860<br>
   * - v8.06 = 806<br>
   * - v1.0.0 = 100<br>
   * - v1.81.65 = 181
   *
   * @return version parsed to an Integer
   */
  public int getVersionNumber() {
    String ver = this.getVersion();
    // Get first dot index
    int dotIndex = ver.indexOf('.');
    if (dotIndex != -1) {
      // Get second dot index from first dot index
      dotIndex = ver.indexOf('.', dotIndex + 1);
      if (dotIndex != -1) {
        // Trim this trailing part
        ver = ver.substring(0, dotIndex);
      }
    }
    return (int) (100.0 * ParseUtil.parseDouble(ver, 1.0));
  }

  /**
   * Gets the file of the path relative to this plugin's data folder
   *
   * @param path of the file
   * @return relative data File
   */
  public File getDataFile(String... path) {
    if (path == null || path.length == 0) {
      return this.getDataFolder();
    }
    return new File(this.getDataFolder(), StringUtil.join(File.separator, path));
  }

  /**
   * Gets a Permission, creates one if it doesn't exist
   *
   * @param path of the Permission to obtain
   * @return Permission
   */
  public static Permission getPermission(String path) {
    return CommonPlugin.getInstance().getPermissionHandler().getPermission(path);
  }

  /**
   * Gets a permission configuration node
   *
   * @param path of the node to get
   * @return Permission configuration node
   */
  public final ConfigurationNode getPermissionNode(String path) {
    return this.permissionconfig.getNode(path);
  }

  /**
   * Gets a localization configuration node
   *
   * @param path of the node to get
   * @return Localization configuration node
   */
  public final ConfigurationNode getLocalizationNode(String path) {
    return this.localizationconfig.getNode(path);
  }

  /**
   * Registers this main class for one or more commands
   *
   * @param commands to register this Plugin class for
   */
  public final void register(String... commands) {
    this.register(this, commands);
  }

  /**
   * Registers a command executor for one or more commands
   *
   * @param executor to register
   * @param commands to register it for
   */
  public final void register(CommandExecutor executor, String... commands) {
    for (String command : commands) {
      PluginCommand cmd = this.getCommand(command);
      if (cmd != null) {
        cmd.setExecutor(executor);
      }
    }
  }

  /**
   * Registers a listener instance
   *
   * @param listener to register
   */
  public final void register(Listener listener) {
    if (listener == null) {
      throw new RuntimeException("Can not load a listener: The listener instance is null");
    }
    if (listener != this) {
      Bukkit.getPluginManager().registerEvents(listener, this);
    }
  }

  /**
   * Registers a listener class
   *
   * @param listener class to register
   */
  public final void register(Class<? extends Listener> listener) {
    if (listener == null) {
      throw new RuntimeException("Can not load a listener: The listener class is null");
    }
    try {
      this.register(listener.newInstance());
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  /**
   * Registers a packet monitor for the packet types specified.
   * Monitors can only monitor packets, they can not alter them.
   *
   * @param packetMonitor to register
   * @param packetTypes to register the listener for
   */
  public final void register(PacketMonitor packetMonitor, PacketType... packetTypes) {
    PacketUtil.addPacketMonitor(this, packetMonitor, packetTypes);
  }

  /**
   * Registers a packet listener for the packet types specified.
   * Listeners are able to modify packets.
   *
   * @param packetListener to register
   * @param packetTypes to register the listener for
   */
  public final void register(PacketListener packetListener, PacketType... packetTypes) {
    PacketUtil.addPacketListener(this, packetListener, packetTypes);
  }

  /**
   * Unregisters a packet listener
   *
   * @param packetListener to unregister
   */
  public final void unregister(PacketListener packetListener) {
    PacketUtil.removePacketListener(packetListener);
  }

  /**
   * Loads all the permissions from a Permissions container class<br>
   * If the class is not an enumeration, the static constants in the class are used instead
   *
   * @param permissionDefaults class
   */
  public final void loadPermissions(Class<? extends IPermissionDefault> permissionDefaults) {
    for (IPermissionDefault def : CommonUtil.getClassConstants(permissionDefaults)) {
      this.loadPermission(def);
    }
  }

  /**
   * Loads a single permission using a permission default
   *
   * @param permissionDefault to use
   * @return Permission that was loaded
   */
  public final Permission loadPermission(IPermissionDefault permissionDefault) {
    return this.loadPermission(permissionDefault.getName(), permissionDefault.getDefault(), permissionDefault.getDescription());
  }

  /**
   * Loads a single permission using a permission path
   *
   * @param path of the Permission
   * @return Permission that was loaded
   */
  public final Permission loadPermission(String path) {
    return this.loadPermission(getPermission(path));
  }

  /**
   * Loads a single permission using a Permission
   *
   * @param permission to load
   * @return Permission that was loaded
   */
  public final Permission loadPermission(Permission permission) {
    return this.loadPermission(permission.getName(), permission.getDefault(), permission.getDescription());
  }

  /**
   * Loads a single permission using the path, default and description
   *
   * @param path of the Permission
   * @param def value of the Permission
   * @param description value of the Permission
   * @return Permission that was loaded
   */
  public final Permission loadPermission(String path, PermissionDefault def, String description) {
    return this.loadPermission(getPermissionNode(path), def, description);
  }

  /**
   * Loads a single permission using the configuration node, default and description
   *
   * @param node to use for the permission path, default and description
   * @param def value to use if the node is unusable
   * @param description to use if the node is unusable
   * @return Permission that was loaded
   */
  public final Permission loadPermission(ConfigurationNode node, PermissionDefault def, String description) {
    Permission permission = getPermission(node.getPath());
    permission.setDefault(node.get("default", def));
    permission.setDescription(node.get("description", description));
    return permission;
  }

  /**
   * Loads all the localization defaults from a Localization container class<br>
   * If the class is not an enumeration, the static constants in the class are used instead
   *
   * @param localizationDefaults class
   */
  public void loadLocales(Class<? extends ILocalizationDefault> localizationDefaults) {
    for (ILocalizationDefault def : CommonUtil.getClassConstants(localizationDefaults)) {
      this.loadLocale(def);
    }
  }

  /**
   * Loads a localization using a localization default
   *
   * @param localizationDefault to load from
   */
  public void loadLocale(ILocalizationDefault localizationDefault) {
    this.loadLocale(localizationDefault.getName(), localizationDefault.getDefault());
  }

  /**
   * Loads a single Localization value<br>
   * Adds this node to the localization configuration if it wsn't added
   *
   * @param path to the value (case insensitive, can not be null)
   * @param defaultValue for the value
   */
  public void loadLocale(String path, String defaultValue) {
    path = path.toLowerCase(Locale.ENGLISH);
    if (!this.localizationconfig.contains(path)) {
      this.localizationconfig.set(path, defaultValue);
    }
  }

  /**
   * Tries to find the command configuration for a command
   *
   * @param command to find the configuration node for
   * @return The configuration node, or null if not found
   */
  private ConfigurationNode getCommandNode(String command) {
    command = command.toLowerCase(Locale.ENGLISH);
    String fullPath = "commands." + command;
    if (this.localizationconfig.isNode(fullPath)) {
      return this.localizationconfig.getNode(fullPath);
    } else {
      fullPath = "commands." + command.replace('.', ' ');
      if (this.localizationconfig.isNode(fullPath)) {
        return this.localizationconfig.getNode(fullPath);
      } else {
        return null;
      }
    }
  }

  /**
   * Gets the localized usage for a command
   *
   * @param command name (case insensitive)
   * @return command usage
   */
  public String getCommandUsage(String command) {
    ConfigurationNode node = getCommandNode(command);
    final String defValue = "/" + command;
    if (node == null) {
      return defValue;
    } else {
      return node.get("usage", defValue);
    }
  }

  /**
   * Gets the localized description for a command
   *
   * @param command name (case insensitive)
   * @return command description
   */
  public String getCommandDescription(String command) {
    ConfigurationNode node = getCommandNode(command);
    final String defValue = "No description specified";
    if (node == null) {
      return defValue;
    } else {
      return node.get("description", defValue);
    }
  }

  /**
   * Gets a localization value
   *
   * @param path to the localization value (case insensitive, can not be null)
   * @param arguments to use for the value
   * @return Localization value
   */
  public String getLocale(String path, String... arguments) {
    path = path.toLowerCase(Locale.ENGLISH);
    // First check if the path leads to a node
    if (this.localizationconfig.isNode(path)) {
      // Redirect to the proper sub-node
      // Check recursively if the arguments are contained
      String newPath = path + ".default";
      if (arguments.length > 0) {
        StringBuilder tmpPathBuilder = new StringBuilder(path);
        String tmpPath = path;
        for (int i = 0; i < arguments.length; i++) {
          tmpPathBuilder.append('.');
          if (arguments[i] == null) {
            tmpPathBuilder.append("null");
          } else {
            tmpPathBuilder.append(arguments[i].toLowerCase(Locale.ENGLISH));
          }
          tmpPath = tmpPathBuilder.toString();
          // New argument appended path exists, update the path
          if (this.localizationconfig.contains(tmpPath)) {
            newPath = tmpPath;
          } else {
            break;
          }
        }
      }
      // Update path to lead to the new path
      path = newPath;
    }
    // Regular loading going on
    if (arguments.length > 0) {
      StringBuilder locale = new StringBuilder(this.localizationconfig.get(path, ""));
      for (int i = 0; i < arguments.length; i++) {
        StringUtil.replaceAll(locale, "%" + i + "%", LogicUtil.fixNull(arguments[i], "null"));
      }
      return locale.toString();
    } else {
      return this.localizationconfig.get(path, String.class, "");
    }
  }

  /**
   * Fired when the Permission nodes have to be created
   */
  public void permissions() {
  }

  /**
   * Fired when the Localization nodes have to be created
   */
  public void localization() {
  }

  /**
   * Gets the disable message shown when this Plugin disables
   *
   * @return disable message
   */
  public final String getDisableMessage() {
    return this.disableMessage;
  }

  /**
   * Sets the disable message shown when this Plugin disables
   *
   * @param msg to set to, null to disable the message
   */
  public void setDisableMessage(String msg) {
    this.disableMessage = msg;
  }

  /**
   * Gets the enable message shown after this Plugin enabled successfully
   *
   * @return enable message
   */
  public final String getEnableMessage() {
    return this.enableMessage;
  }

  /**
   * Sets the enable message shown after this Plugin enabled successfully
   *
   * @param msg to set to, null to disable the message
   */
  public void setEnableMessage(String msg) {
    this.enableMessage = msg;
  }

  /**
   * Gets the minimum BKCommonLib version required for this Plugin to function<br>
   * Override this and return Common.VERSION as result (compiler will automatically inline this)
   *
   * @return Minimum BKCommonLib version number
   */
  public abstract int getMinimumLibVersion();

  /**
   * Handles a possible throwable thrown somewhere in the Plugin<br>
   * If the throwable is too severe, the plugin is automatically disabled<br>
   * Additional exception types can be handled if needed
   *
   * @param reason to throw
   */
  @SuppressWarnings("unchecked")
  public void handle(Throwable reason) {
    if (reason instanceof Exception) {
      StackTraceFilter.SERVER.print(reason);
    } else if (reason instanceof OutOfMemoryError) {
      log(Level.SEVERE, "The server is running out of memory! Do something!");
    } else {
      String pluginCause = getName();
      if (CommonUtil.isInstance(reason, NoClassDefFoundError.class, NoSuchMethodError.class, NoSuchFieldError.class, IllegalAccessError.class)) {
        String fixedReason = StringUtil.trimStart(reason.getMessage(), "tried to access ");
        String path = StringUtil.trimStart(fixedReason, "method ", "field ", "class ");
        if (path.startsWith(Common.NMS_ROOT)) {
          log(Level.SEVERE, "This version of the plugin is incompatible with this Minecraft version:");
        } else if (path.startsWith(Common.CB_ROOT)) {
          log(Level.SEVERE, "This version of the plugin is incompatible with this CraftBukkit implementation:");
        } else if (path.startsWith("org.bukkit")) {
          log(Level.SEVERE, "This version of the plugin is incompatible with the current Bukkit API:");
        } else {
          final Plugin plugin = CommonUtil.getPluginByClass(path);
          if (plugin == this) {
            if (reason instanceof NoClassDefFoundError) {
              log(Level.WARNING, "Class is missing (plugin was hot-swapped?): " + reason.getMessage());
              return;
            } else {
              log(Level.SEVERE, "Encountered a compiler error");
            }
          } else {
            // Obtain the type of happening
            final String type;
            if (reason instanceof IllegalAccessError) {
              if (fixedReason.startsWith("class ")) {
                type = "Class is inaccessible in";
              } else if (fixedReason.startsWith("method ")) {
                type = "Method is inaccessible in";
              } else if (fixedReason.startsWith("field ")) {
                type = "Field is inaccessible in";
              } else {
                type = "Something is inaccessible in";
              }
            } else if (reason instanceof NoClassDefFoundError) {
              type = "Class is missing from";
            } else if (reason instanceof NoSuchMethodError) {
              type = "Method is missing from";
            } else if (reason instanceof NoSuchFieldError) {
              type = "Field is missing from";
            } else {
              type = "Something is missing from";
            }
            // Log the message
            if (plugin == null) {
              log(Level.SEVERE, type + " a dependency of this plugin");
              // Add all dependencies of this plugin to the cause
              LinkedHashSet<String> dep = new LinkedHashSet<String>();
              dep.add(this.getName());
              dep.addAll(LogicUtil.fixNull(this.getDescription().getDepend(), Collections.EMPTY_LIST));
              dep.addAll(LogicUtil.fixNull(this.getDescription().getSoftDepend(), Collections.EMPTY_LIST));
              pluginCause = StringUtil.combineNames(dep);
            } else {
              pluginCause = getName() + " and " + plugin.getName();
              log(Level.SEVERE, type + " dependency '" + plugin.getName() + "'");
            }
          }
        }
      } else {
        log(Level.SEVERE, "Encountered a critical error");
      }
      log(Level.SEVERE, "Please, check for an updated version of " + pluginCause + " before reporting this bug!");
      StackTraceFilter.SERVER.print(reason);
    }
  }

  private static void setPermissions(ConfigurationNode node) {
    for (ConfigurationNode subNode : node.getNodes()) {
      setPermissions(subNode);
    }
    PermissionDefault def = node.get("default", PermissionDefault.class);
    String desc = node.get("description", String.class);
    if (def != null || desc != null) {
      Permission permission = getPermission(node.getPath().toLowerCase());
      if (def != null) {
        permission.setDefault(def);
      }
      if (desc != null) {
        permission.setDescription(desc);
      }
    }
  }

  /**
   * Gets the Metrics instance for this Plugin, which is used to send statistics to
   * <a href="http://mcstats.org/">http://mcstats.org/</a><br>
   * To make use of this functionality, first add the following line to the <b>plugin.yml</b>:<br>
   * <pre>metrics: true</pre>
   *
   * To avoid issues, call {@link #hasMetrics()} before using this method to check whether Metrics is available.
   *
   * @return the Metrics instance used
   * @throws RuntimeException if no metrics is available
   */
  public Metrics getMetrics() {
    if (metrics == null) {
      throw new RuntimeException("Metrics is not enabled or failed to initialize for this Plugin.");
    }
    return metrics;
  }

  /**
   * Checks whether Metrics is available for this Plugin. Always call this method
   * before using {@link #getMetrics()} - initialization of Metrics could have failed!
   *
   * @return True if Metrics is available, False if not
   */
  public boolean hasMetrics() {
    return metrics != null;
  }

  @Override
  @SuppressWarnings("unchecked")
  public final void onEnable() {
    // Shortcut to avoid unneeded initialization: calling enable will result in BKCommonLib disabling
    if (!Common.IS_COMPATIBLE && this instanceof CommonPlugin) {
      this.enable();
      return;
    }
    // First of all, check that all dependencies are properly enabled
    for (String dep : LogicUtil.fixNull(getDescription().getDepend(), (List<String>) Collections.EMPTY_LIST)) {
      if (!Bukkit.getPluginManager().isPluginEnabled(dep)) {
        log(Level.SEVERE, "Could not enable '" + getName() + " v" + getVersion() + "' because dependency '" + dep + "' failed to enable!");
        log(Level.SEVERE, "Perhaps the dependency has to be updated? Please check the log for any errors related to " + dep);
        Bukkit.getPluginManager().disablePlugin(this);
        return;
      }
    }

    long startTime = System.currentTimeMillis();
    if (this.getMinimumLibVersion() > Common.VERSION) {
      log(Level.SEVERE, "Requires a newer BKCommonLib version, please update BKCommonLib to the latest version!");
      log(Level.SEVERE, "Verify that there is only one BKCommonLib.jar in the plugins folder before retrying");
      Bukkit.getPluginManager().disablePlugin(this);
      return;
    }

    this.setDisableMessage(this.getName() + " disabled!");

    // Load permission configuration
    this.permissionconfig = new FileConfiguration(this, "PermissionDefaults.yml");
    // load
    if (this.permissionconfig.exists()) {
      this.loadPermissions();
    }
    // header
    this.permissionconfig.setHeader("Below are the default permissions set for plugin '" + this.getName() + "'.");
    this.permissionconfig.addHeader("These permissions are ignored if the permission is set for a group or player.");
    this.permissionconfig.addHeader("Use the defaults as a base to keep the permissions file small");
    this.permissionconfig.addHeader("Need help with this file? Please visit:");
    this.permissionconfig.addHeader("http://dev.bukkit.org/server-mods/bkcommonlib/pages/general/permission-defaults/");

    // Load localization configuration
    this.localizationconfig = new FileConfiguration(this, "Localization.yml");
    // load
    if (this.localizationconfig.exists()) {
      this.loadLocalization();
    }

    // header
    this.localizationconfig.setHeader("Below are the localization nodes set for plugin '" + this.getName() + "'.");
    this.localizationconfig.addHeader("For colors, use the & character followed up by 0 - F");
    this.localizationconfig.addHeader("Need help with this file? Please visit:");
    this.localizationconfig.addHeader("http://dev.bukkit.org/server-mods/bkcommonlib/pages/general/localization/");

    // Load plugin.yml configuration
    try {
      this.pluginYaml.loadFromStream(getResource("plugin.yml"));
    } catch (Exception ex) {
      Bukkit.getLogger().log(Level.SEVERE, "[Configuration] An error occured while loading plugin.yml resource for plugin " + getName() + ":");
    }

    // Load all the commands for this Plugin
    Map<String, Map<String, Object>> commands = this.getDescription().getCommands();
    if (commands != null && PluginDescriptionFileRef.commands.isValid()) {
      // Prepare commands localization node
      ConfigurationNode commandsNode = getLocalizationNode("commands");

      // Create a new modifiable commands map to replace with
      commands = new HashMap<String, Map<String, Object>>(commands);
      for (Entry<String, Map<String, Object>> commandEntry : commands.entrySet()) {
        ConfigurationNode node = commandsNode.getNode(commandEntry.getKey());

        // Transfer description and usage
        Map<String, Object> data = new HashMap<String, Object>(commandEntry.getValue());
        node.shareWith(data, "description", "No description specified");
        node.shareWith(data, "usage", "/" + commandEntry.getKey());
        commandEntry.setValue(Collections.unmodifiableMap(data));
      }

      // Set the new commands map using reflection
      PluginDescriptionFileRef.commands.set(this.getDescription(), Collections.unmodifiableMap(commands));
    }

    // ==== Permissions ====
    this.permissions();
    // Load all nodes from the permissions config
    setPermissions(this.permissionconfig);
    if (!this.permissionconfig.isEmpty()) {
      this.savePermissions();
    }

    // ==== Localization ====
    this.localization();
    if (!this.localizationconfig.isEmpty()) {
      this.saveLocalization();
    }

    // ==== Enabling ====
    try {
      // Metrics
      if (this.pluginYaml.get("metrics", false)) {
        // Send anonymous statistics to mcstats.org
        try {
          this.metrics = new Metrics(this);
        } catch (IOException ex) {
          log(Level.SEVERE, "Failed to initialize metrics for " + getName());
          CommonUtil.printFilteredStackTrace(ex);
        }
      }

      this.wasDisableRequested = false;
      this.enable();
      if (this.wasDisableRequested) {
        // Plugin was disabled again while enabling
        return;
      }

      // Start Metrics if enabled
      if (metrics != null) {
        metrics.start();
      }

      // Done, this plugin is enabled
      this.enabled = true;
    } catch (Throwable t) {
      log(Level.SEVERE, "An error occurred while enabling, the plugin will be disabled:");
      handle(t);
      Bukkit.getPluginManager().disablePlugin(this);
      return;
    }

    // update dependencies
    CommonPlugin.getInstance().plugins.add(this);
    for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) {
      if (plugin.isEnabled()) {
        this.updateDependency(plugin, plugin.getName(), true);
      }
    }

    // Enable messages
    if (this.enableMessage != null) {
      log(Level.INFO, this.enableMessage);
    }
    Bukkit.getLogger().log(Level.INFO, this.getName() + " version " + this.getVersion() + " enabled! (" + MathUtil.round(0.001 * (System.currentTimeMillis() - startTime), 3) + "s)");
  }

  @Override
  public final void onDisable() {
    // are there any plugins that depend on me?
    for (Plugin plugin : Bukkit.getServer().getPluginManager().getPlugins()) {
      if (plugin.isEnabled() && CommonUtil.isDepending(plugin, this)) {
        Bukkit.getServer().getPluginManager().disablePlugin(plugin);
      }
    }
    this.wasDisableRequested = true;
    boolean doDisableMessage = this.disableMessage != null;
    if (this.enabled) {
      // Try to disable the plugin
      try {
        this.disable();
      } catch (Throwable t) {
        log(Level.SEVERE, "An error occurred while disabling:");
        StackTraceFilter.SERVER.print(t);
        doDisableMessage = false;
      }
      // Remove references to the plugin - it is disabled now
      this.enabled = false;
      if (CommonPlugin.hasInstance()) {
        CommonPlugin.getInstance().plugins.remove(this);
      }
    }
    // Disable Metrics if enabled
    if (metrics != null) {
      metrics.stop();
      metrics = null;
    }

    // If specified to do so, a disable message is shown
    if (doDisableMessage) {
      Bukkit.getLogger().log(Level.INFO, this.disableMessage);
    }
  }

  @Override
  public final boolean onCommand(CommandSender sender, org.bukkit.command.Command cmd, String command, String[] args) {
    try {
      String[] fixedArgs = StringUtil.convertArgs(args);
      // Default commands for all plugins
      if (fixedArgs.length >= 1 && LogicUtil.contains(fixedArgs[0].toLowerCase(Locale.ENGLISH), "version", "ver")) {
        sender.sendMessage(ChatColor.GREEN + this.getName() + " v" + this.getVersion() + " using BKCommonLib v" + CommonPlugin.getInstance().getVersion());
      }
      // Handle regularly
      if (command(sender, command, fixedArgs)) {
        return true;
      }
      sender.sendMessage(ChatColor.RED + "Unknown command, for help use /help " + command);
    } catch (NoPermissionException ex) {
      if (sender instanceof Player) {
        sender.sendMessage(ChatColor.RED + "You do not have permission to use this command!");
      } else {
        sender.sendMessage("This command is only for players!");
      }
    } catch (Throwable t) {
      StringBuilder msg = new StringBuilder("Unhandled exception executing command '");
      msg.append(command).append("' in plugin ").append(this.getName()).append(" v").append(this.getVersion());
      Bukkit.getLogger().log(Level.SEVERE, msg.toString());
      t.printStackTrace();
      sender.sendMessage(ChatColor.RED + "An internal error occured while executing this command");
    }
    return true;
  }

  /**
   * Called when this plugin is being enabled
   */
  public abstract void enable();

  /**
   * Called when this plugin is being disabled
   */
  public abstract void disable();

  /**
   * Handles a command
   *
   * @param sender of the command
   * @param command name
   * @param args of the command
   * @return True if handled, False if not
   */
  public abstract boolean command(CommandSender sender, String command, String[] args);

  public final void loadLocalization() {
    this.localizationconfig.load();
  }

  /**
   * Obtains a configuration instance managed by this PluginBase containing the contents of the plugin.yml
   *
   * @return plugin.yml configuration
   */
  public final BasicConfiguration getPluginYaml() {
    return this.pluginYaml;
  }

  public final void saveLocalization() {
    this.localizationconfig.save();
  }
 
  public final void loadPermissions() {
    this.permissionconfig.load();
  }

  public final void savePermissions() {
    this.permissionconfig.save();
  }

  /**
   * Called when a plugin is enabled or disabled
   *
   * @param plugin that got enabled or disabled
   * @param pluginName of the plugin
   * @param enabled state, True if enabled, False if disabled
   */
  public void updateDependency(Plugin plugin, String pluginName, boolean enabled) {
  };
}
TOP

Related Classes of com.bergerkiller.bukkit.common.PluginBase

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.