ProtocolLib/src/main/java/com/comphenix/protocol/ProtocolLib.java

662 lines
21 KiB
Java
Raw Normal View History

/**
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
* Copyright (C) 2012 Kristian S. Stangeland
*
2014-11-24 17:41:04 +01:00
* 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 2 of
* the License, or (at your option) any later version.
*
2014-11-24 17:41:04 +01:00
* 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.
*
2014-11-24 17:41:04 +01:00
* You should have received a copy of the GNU General Public License along with this program;
* if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307 USA
*/
package com.comphenix.protocol;
import java.io.File;
import java.io.IOException;
import java.util.Set;
2012-11-03 06:41:29 +01:00
import java.util.logging.Handler;
import java.util.logging.Level;
2012-11-03 06:41:29 +01:00
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.bukkit.Server;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.PluginCommand;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin;
import com.comphenix.executors.BukkitExecutors;
import com.comphenix.protocol.async.AsyncFilterManager;
import com.comphenix.protocol.error.BasicErrorReporter;
import com.comphenix.protocol.error.DelegatedErrorReporter;
2012-10-29 04:17:53 +01:00
import com.comphenix.protocol.error.DetailedErrorReporter;
import com.comphenix.protocol.error.ErrorReporter;
import com.comphenix.protocol.error.Report;
import com.comphenix.protocol.error.ReportType;
import com.comphenix.protocol.injector.DelayedSingleTask;
import com.comphenix.protocol.injector.InternalManager;
import com.comphenix.protocol.injector.PacketFilterManager;
2016-03-19 21:01:38 +01:00
import com.comphenix.protocol.injector.PlayerInjectHooks;
import com.comphenix.protocol.metrics.Statistics;
import com.comphenix.protocol.reflect.compiler.BackgroundCompiler;
import com.comphenix.protocol.updater.Updater;
import com.comphenix.protocol.updater.Updater.UpdateType;
import com.comphenix.protocol.utility.ChatExtensions;
import com.comphenix.protocol.utility.EnhancerFactory;
import com.comphenix.protocol.utility.MinecraftVersion;
import com.google.common.base.Splitter;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import com.google.common.util.concurrent.ListeningScheduledExecutorService;
/**
* The main entry point for ProtocolLib.
2014-11-24 17:41:04 +01:00
*
* @author Kristian
*/
2016-03-19 21:01:38 +01:00
public class ProtocolLib extends JavaPlugin {
// Every possible error or warning report type
public static final ReportType REPORT_CANNOT_LOAD_CONFIG = new ReportType("Cannot load configuration");
public static final ReportType REPORT_CANNOT_DELETE_CONFIG = new ReportType("Cannot delete old ProtocolLib configuration.");
public static final ReportType REPORT_CANNOT_PARSE_INJECTION_METHOD = new ReportType("Cannot parse injection method. Using default.");
2014-11-24 17:41:04 +01:00
public static final ReportType REPORT_PLUGIN_LOAD_ERROR = new ReportType("Cannot load ProtocolLib.");
public static final ReportType REPORT_PLUGIN_ENABLE_ERROR = new ReportType("Cannot enable ProtocolLib.");
2014-11-24 17:41:04 +01:00
public static final ReportType REPORT_METRICS_IO_ERROR = new ReportType("Unable to enable metrics due to network problems.");
public static final ReportType REPORT_METRICS_GENERIC_ERROR = new ReportType("Unable to enable metrics due to network problems.");
2014-11-24 17:41:04 +01:00
public static final ReportType REPORT_CANNOT_PARSE_MINECRAFT_VERSION = new ReportType("Unable to retrieve current Minecraft version. Assuming %s");
public static final ReportType REPORT_CANNOT_DETECT_CONFLICTING_PLUGINS = new ReportType("Unable to detect conflicting plugin versions.");
public static final ReportType REPORT_CANNOT_REGISTER_COMMAND = new ReportType("Cannot register command %s: %s");
2014-11-24 17:41:04 +01:00
public static final ReportType REPORT_CANNOT_CREATE_TIMEOUT_TASK = new ReportType("Unable to create packet timeout task.");
public static final ReportType REPORT_CANNOT_UPDATE_PLUGIN = new ReportType("Cannot perform automatic updates.");
2014-11-24 17:41:04 +01:00
// Update information
static final String BUKKIT_DEV_SLUG = "protocollib";
static final int BUKKIT_DEV_ID = 45564;
// Different commands
private enum ProtocolCommand {
FILTER,
PACKET,
2017-03-01 23:02:46 +01:00
PROTOCOL,
LOGGING;
}
2014-11-24 17:41:04 +01:00
2012-11-04 03:03:38 +01:00
/**
* The number of milliseconds per second.
*/
static final long MILLI_PER_SECOND = 1000;
2014-11-24 17:41:04 +01:00
2012-11-03 06:41:29 +01:00
private static final String PERMISSION_INFO = "protocol.info";
2014-11-24 17:41:04 +01:00
// There should only be one protocol manager, so we'll make it static
private static InternalManager protocolManager;
2014-11-24 17:41:04 +01:00
2012-10-29 04:17:53 +01:00
// Error reporter
private static ErrorReporter reporter = new BasicErrorReporter();
2014-11-24 17:41:04 +01:00
2014-02-02 19:45:30 +01:00
// Strongly typed configuration
private static ProtocolConfig config;
2014-11-24 17:41:04 +01:00
// Metrics and statistics
private Statistics statistics;
// Executors
private static ListeningScheduledExecutorService executorAsync;
private static ListeningScheduledExecutorService executorSync;
2014-11-24 17:41:04 +01:00
// Structure compiler
private BackgroundCompiler backgroundCompiler;
2014-11-24 17:41:04 +01:00
// Used to clean up server packets that have expired, but mostly required to simulate
// recieving client packets.
2013-12-29 11:58:54 +01:00
private int packetTask = -1;
private int tickCounter = 0;
2013-12-29 11:58:54 +01:00
private static final int ASYNC_MANAGER_DELAY = 1;
2014-11-24 17:41:04 +01:00
// Used to unhook players after a delay
private DelayedSingleTask unhookTask;
2014-11-24 17:41:04 +01:00
// Settings/options
2013-12-29 11:58:54 +01:00
private int configExpectedMod = -1;
2014-11-24 17:41:04 +01:00
// Updater
private Updater updater;
2016-02-18 03:48:24 +01:00
public static boolean UPDATES_DISABLED;
// Logger
private static Logger logger;
private Handler redirectHandler;
2014-11-24 17:41:04 +01:00
// Commands
private CommandProtocol commandProtocol;
private CommandPacket commandPacket;
private CommandFilter commandFilter;
2017-03-01 23:02:46 +01:00
private PacketLogging packetLogging;
2014-11-24 17:41:04 +01:00
// Whether or not disable is not needed
private boolean skipDisable;
2014-11-24 17:41:04 +01:00
@Override
public void onLoad() {
// Logging
logger = getLogger();
ProtocolLogger.init(this);
// Initialize enhancer factory
EnhancerFactory.getInstance().setClassLoader(getClassLoader());
2014-11-24 17:41:04 +01:00
// Initialize executors
executorAsync = BukkitExecutors.newAsynchronous(this);
executorSync = BukkitExecutors.newSynchronous(this);
2014-11-24 17:41:04 +01:00
2012-10-29 04:17:53 +01:00
// Add global parameters
DetailedErrorReporter detailedReporter = new DetailedErrorReporter(this);
reporter = getFilteredReporter(detailedReporter);
2014-11-24 17:41:04 +01:00
// Configuration
saveDefaultConfig();
reloadConfig();
2012-11-03 00:54:03 +01:00
try {
config = new ProtocolConfig(this);
} catch (Exception e) {
reporter.reportWarning(this, Report.newBuilder(REPORT_CANNOT_LOAD_CONFIG).error(e));
2012-11-04 03:03:38 +01:00
2012-11-03 00:54:03 +01:00
// Load it again
if (deleteConfig()) {
config = new ProtocolConfig(this);
} else {
reporter.reportWarning(this, Report.newBuilder(REPORT_CANNOT_DELETE_CONFIG));
}
2012-11-03 00:54:03 +01:00
}
2014-11-24 17:41:04 +01:00
// Print the state of the debug mode
if (config.isDebug()) {
logger.warning("Debug mode is enabled!");
}
// And the state of the error reporter
if (config.isDetailedErrorReporting()) {
detailedReporter.setDetailedReporting(true);
logger.warning("Detailed error reporting enabled!");
}
2014-11-24 17:41:04 +01:00
2012-10-29 04:17:53 +01:00
try {
// Check for other versions
checkConflictingVersions();
2014-11-24 17:41:04 +01:00
// Handle unexpected Minecraft versions
MinecraftVersion version = verifyMinecraftVersion();
2014-11-24 17:41:04 +01:00
// Set updater - this will not perform any update automatically
updater = Updater.create(this, BUKKIT_DEV_ID, getFile(), UpdateType.NO_DOWNLOAD, true);
2012-10-29 04:17:53 +01:00
unhookTask = new DelayedSingleTask(this);
protocolManager = PacketFilterManager.newBuilder()
.classLoader(getClassLoader())
.server(getServer())
.library(this)
.minecraftVersion(version)
.unhookTask(unhookTask)
.reporter(reporter)
.build();
2014-11-24 17:41:04 +01:00
2016-03-19 21:01:38 +01:00
// Initialize the API
ProtocolLibrary.init(this, config, protocolManager, reporter, executorAsync, executorSync);
// Setup error reporter
detailedReporter.addGlobalParameter("manager", protocolManager);
2014-11-24 17:41:04 +01:00
// Update injection hook
try {
2013-01-13 14:58:07 +01:00
PlayerInjectHooks hook = config.getInjectionMethod();
2013-01-13 14:58:07 +01:00
// Only update the hook if it's different
if (!protocolManager.getPlayerHook().equals(hook)) {
logger.info("Changing player hook from " + protocolManager.getPlayerHook() + " to " + hook);
2013-01-13 14:58:07 +01:00
protocolManager.setPlayerHook(hook);
}
} catch (IllegalArgumentException e) {
reporter.reportWarning(config, Report.newBuilder(REPORT_CANNOT_PARSE_INJECTION_METHOD).error(e));
}
2014-11-24 17:41:04 +01:00
2012-11-03 06:41:29 +01:00
// Send logging information to player listeners too
initializeCommands();
setupBroadcastUsers(PERMISSION_INFO);
2014-11-24 17:41:04 +01:00
} catch (OutOfMemoryError e) {
throw e;
2012-10-29 04:17:53 +01:00
} catch (Throwable e) {
reporter.reportDetailed(this, Report.newBuilder(REPORT_PLUGIN_LOAD_ERROR).error(e).callerParam(protocolManager));
disablePlugin();
2012-10-29 04:17:53 +01:00
}
}
/**
* Initialize all command handlers.
*/
private void initializeCommands() {
// Initialize command handlers
for (ProtocolCommand command : ProtocolCommand.values()) {
try {
switch (command) {
case PROTOCOL:
commandProtocol = new CommandProtocol(reporter, this, updater, config);
break;
case FILTER:
commandFilter = new CommandFilter(reporter, this, config);
break;
case PACKET:
commandPacket = new CommandPacket(reporter, this, logger, commandFilter, protocolManager);
break;
2017-03-01 23:02:46 +01:00
case LOGGING:
packetLogging = new PacketLogging(this, protocolManager);
break;
}
} catch (OutOfMemoryError e) {
throw e;
} catch (LinkageError e) {
logger.warning("Failed to register command " + command.name() + ": " + e);
} catch (Throwable e) {
reporter.reportWarning(this, Report.newBuilder(REPORT_CANNOT_REGISTER_COMMAND)
.messageParam(command.name(), e.getMessage()).error(e));
}
}
}
2014-11-24 17:41:04 +01:00
/**
* Retrieve a error reporter that may be filtered by the configuration.
* @return The new default error reporter.
*/
private ErrorReporter getFilteredReporter(ErrorReporter reporter) {
2014-11-24 17:41:04 +01:00
return new DelegatedErrorReporter(reporter) {
private int lastModCount = -1;
private Set<String> reports = Sets.newHashSet();
2014-11-24 17:41:04 +01:00
@Override
protected Report filterReport(Object sender, Report report, boolean detailed) {
try {
String canonicalName = ReportType.getReportName(sender, report.getType());
String reportName = Iterables.getLast(Splitter.on("#").split(canonicalName)).toUpperCase();
2014-11-24 17:41:04 +01:00
if (config != null && config.getModificationCount() != lastModCount) {
// Update our cached set again
reports = Sets.newHashSet(config.getSuppressedReports());
lastModCount = config.getModificationCount();
}
2014-11-24 17:41:04 +01:00
// Cancel reports either on the full canonical name, or just the report name
if (reports.contains(canonicalName) || reports.contains(reportName))
return null;
2014-11-24 17:41:04 +01:00
} catch (Exception e) {
// Only report this with a minor message
logger.warning("Error filtering reports: " + e.toString());
}
// Don't filter anything
return report;
}
};
}
2014-11-24 17:41:04 +01:00
private boolean deleteConfig() {
return config.getFile().delete();
2012-11-03 00:54:03 +01:00
}
2014-11-24 17:41:04 +01:00
@Override
public void reloadConfig() {
super.reloadConfig();
2014-11-24 17:41:04 +01:00
// Reload configuration
2012-11-04 03:03:38 +01:00
if (config != null) {
config.reloadConfig();
}
}
2014-11-24 17:41:04 +01:00
private void setupBroadcastUsers(final String permission) {
// Guard against multiple calls
if (redirectHandler != null)
return;
2014-11-24 17:41:04 +01:00
// Broadcast information to every user too
redirectHandler = new Handler() {
2012-11-03 06:41:29 +01:00
@Override
public void publish(LogRecord record) {
// Only display warnings and above
if (record.getLevel().intValue() >= Level.WARNING.intValue()) {
commandPacket.broadcastMessageSilently(record.getMessage(), permission);
}
2012-11-03 06:41:29 +01:00
}
2014-11-24 17:41:04 +01:00
2012-11-03 06:41:29 +01:00
@Override
public void flush() {
// Not needed.
}
2014-11-24 17:41:04 +01:00
2012-11-03 06:41:29 +01:00
@Override
public void close() throws SecurityException {
// Do nothing.
}
2012-11-20 06:48:05 +01:00
};
logger.addHandler(redirectHandler);
}
2014-11-24 17:41:04 +01:00
@Override
public void onEnable() {
2012-10-29 04:17:53 +01:00
try {
Server server = getServer();
PluginManager manager = server.getPluginManager();
2014-11-24 17:41:04 +01:00
// Don't do anything else!
if (manager == null)
return;
// Silly plugin reloaders!
if (protocolManager == null) {
Logger directLogging = Logger.getLogger("Minecraft");
String[] message = new String[] {
" ProtocolLib does not support plugin reloaders! ", " Please use the built-in reload command! "
};
2014-11-24 17:41:04 +01:00
// Print as severe
for (String line : ChatExtensions.toFlowerBox(message, "*", 3, 1)) {
directLogging.severe(line);
}
disablePlugin();
return;
}
2014-11-24 17:41:04 +01:00
// Check for incompatible plugins
checkForIncompatibility(manager);
2012-10-29 04:17:53 +01:00
// Initialize background compiler
if (backgroundCompiler == null && config.isBackgroundCompilerEnabled()) {
backgroundCompiler = new BackgroundCompiler(getClassLoader(), reporter);
2012-10-29 04:17:53 +01:00
BackgroundCompiler.setInstance(backgroundCompiler);
2014-11-24 17:41:04 +01:00
logger.info("Started structure compiler thread.");
} else {
logger.info("Structure compiler thread has been disabled.");
2012-10-29 04:17:53 +01:00
}
2014-11-24 17:41:04 +01:00
// Set up command handlers
registerCommand(CommandProtocol.NAME, commandProtocol);
registerCommand(CommandPacket.NAME, commandPacket);
registerCommand(CommandFilter.NAME, commandFilter);
2017-03-01 23:02:46 +01:00
registerCommand(PacketLogging.NAME, packetLogging);
2014-11-24 17:41:04 +01:00
2012-10-29 04:17:53 +01:00
// Player login and logout events
protocolManager.registerEvents(manager, this);
2014-11-24 17:41:04 +01:00
2012-10-29 04:17:53 +01:00
// Worker that ensures that async packets are eventually sent
// It also performs the update check.
2013-12-29 11:58:54 +01:00
createPacketTask(server);
} catch (OutOfMemoryError e) {
throw e;
2012-10-29 04:17:53 +01:00
} catch (Throwable e) {
reporter.reportDetailed(this, Report.newBuilder(REPORT_PLUGIN_ENABLE_ERROR).error(e));
2012-10-29 04:17:53 +01:00
disablePlugin();
return;
}
2014-11-24 17:41:04 +01:00
// Try to enable statistics
try {
if (config.isMetricsEnabled()) {
2014-11-24 17:41:04 +01:00
statistics = new Statistics(this);
}
} catch (OutOfMemoryError e) {
throw e;
} catch (IOException e) {
2014-11-24 17:41:04 +01:00
reporter.reportDetailed(this, Report.newBuilder(REPORT_METRICS_IO_ERROR).error(e).callerParam(statistics));
} catch (Throwable e) {
2014-11-24 17:41:04 +01:00
reporter.reportDetailed(this, Report.newBuilder(REPORT_METRICS_GENERIC_ERROR).error(e).callerParam(statistics));
}
}
2014-11-24 17:41:04 +01:00
// Plugin authors: Notify me to remove these
private void checkForIncompatibility(PluginManager manager) {
2016-03-19 21:01:38 +01:00
for (String plugin : ProtocolLibrary.INCOMPATIBLE) {
if (manager.getPlugin(plugin) != null) {
// Special case for TagAPI and iTag
if (plugin.equals("TagAPI")) {
Plugin iTag = manager.getPlugin("iTag");
if (iTag == null || iTag.getDescription().getVersion().startsWith("1.0")) {
logger.severe("Detected incompatible plugin: TagAPI");
}
} else {
logger.severe("Detected incompatible plugin: " + plugin);
}
}
}
}
// Used to check Minecraft version
private MinecraftVersion verifyMinecraftVersion() {
2016-03-19 21:01:38 +01:00
MinecraftVersion minimum = new MinecraftVersion(ProtocolLibrary.MINIMUM_MINECRAFT_VERSION);
MinecraftVersion maximum = new MinecraftVersion(ProtocolLibrary.MAXIMUM_MINECRAFT_VERSION);
2014-11-24 17:41:04 +01:00
try {
MinecraftVersion current = new MinecraftVersion(getServer());
// Skip certain versions
if (!config.getIgnoreVersionCheck().equals(current.getVersion())) {
// We'll just warn the user for now
if (current.compareTo(minimum) < 0)
logger.warning("Version " + current + " is lower than the minimum " + minimum);
if (current.compareTo(maximum) > 0)
logger.warning("Version " + current + " has not yet been tested! Proceed with caution.");
}
return current;
} catch (Exception e) {
reporter.reportWarning(this, Report.newBuilder(REPORT_CANNOT_PARSE_MINECRAFT_VERSION).error(e).messageParam(maximum));
2014-11-24 17:41:04 +01:00
// Unknown version - just assume it is the latest
return maximum;
}
}
private void checkConflictingVersions() {
Pattern ourPlugin = Pattern.compile("ProtocolLib-(.*)\\.jar");
MinecraftVersion currentVersion = new MinecraftVersion(getDescription().getVersion());
MinecraftVersion newestVersion = null;
// Skip the file that contains this current instance however
File loadedFile = getFile();
2014-11-24 17:41:04 +01:00
try {
// Scan the plugin folder for newer versions of ProtocolLib
// The plugin folder isn't always plugins/
File pluginFolder = getDataFolder().getParentFile();
2014-11-24 17:41:04 +01:00
File[] candidates = pluginFolder.listFiles();
if (candidates != null) {
for (File candidate : candidates) {
if (candidate.isFile() && !candidate.equals(loadedFile)) {
Matcher match = ourPlugin.matcher(candidate.getName());
if (match.matches()) {
MinecraftVersion version = new MinecraftVersion(match.group(1));
if (candidate.length() == 0) {
// Delete and inform the user
logger.info((candidate.delete() ? "Deleted " : "Could not delete ") + candidate);
} else if (newestVersion == null || newestVersion.compareTo(version) < 0) {
newestVersion = version;
}
}
}
}
}
} catch (Exception e) {
// TODO This shows [ProtocolLib] and [ProtocolLibrary] in the message
reporter.reportWarning(this, Report.newBuilder(REPORT_CANNOT_DETECT_CONFLICTING_PLUGINS).error(e));
}
2014-11-24 17:41:04 +01:00
// See if the newest version is actually higher
if (newestVersion != null && currentVersion.compareTo(newestVersion) < 0) {
// We don't need to set internal classes or instances to NULL - that would break the other loaded plugin
skipDisable = true;
2014-11-24 17:41:04 +01:00
throw new IllegalStateException(String.format(
"Detected a newer version of ProtocolLib (%s) in plugin folder than the current (%s). Disabling.",
newestVersion.getVersion(), currentVersion.getVersion()));
}
}
2014-11-24 17:41:04 +01:00
private void registerCommand(String name, CommandExecutor executor) {
try {
// Ignore these - they must have printed an error already
2014-11-24 17:41:04 +01:00
if (executor == null)
return;
2014-11-24 17:41:04 +01:00
PluginCommand command = getCommand(name);
2014-11-24 17:41:04 +01:00
// Try to load the command
if (command != null) {
command.setExecutor(executor);
} else {
throw new RuntimeException("plugin.yml might be corrupt.");
}
} catch (RuntimeException e) {
reporter.reportWarning(this, Report.newBuilder(REPORT_CANNOT_REGISTER_COMMAND).messageParam(name, e.getMessage()).error(e));
}
}
2014-11-24 17:41:04 +01:00
2012-10-29 04:17:53 +01:00
/**
* Disable the current plugin.
*/
private void disablePlugin() {
getServer().getPluginManager().disablePlugin(this);
}
2014-11-24 17:41:04 +01:00
2013-12-29 11:58:54 +01:00
private void createPacketTask(Server server) {
try {
2013-12-29 11:58:54 +01:00
if (packetTask >= 0)
throw new IllegalStateException("Packet task has already been created");
2014-11-24 17:41:04 +01:00
// Attempt to create task
2013-12-29 11:58:54 +01:00
packetTask = server.getScheduler().scheduleSyncRepeatingTask(this, new Runnable() {
@Override
public void run() {
AsyncFilterManager manager = (AsyncFilterManager) protocolManager.getAsynchronousManager();
2014-11-24 17:41:04 +01:00
// We KNOW we're on the main thread at the moment
manager.sendProcessedPackets(tickCounter++, true);
2014-11-24 17:41:04 +01:00
// House keeping
updateConfiguration();
// Check for updates too
if (!UPDATES_DISABLED && (tickCounter % 20) == 0) {
checkUpdates();
}
}
}, ASYNC_MANAGER_DELAY, ASYNC_MANAGER_DELAY);
} catch (OutOfMemoryError e) {
throw e;
} catch (Throwable e) {
2013-12-29 11:58:54 +01:00
if (packetTask == -1) {
reporter.reportDetailed(this, Report.newBuilder(REPORT_CANNOT_CREATE_TIMEOUT_TASK).error(e));
}
}
}
2014-11-24 17:41:04 +01:00
2013-12-29 11:58:54 +01:00
private void updateConfiguration() {
if (config != null && config.getModificationCount() != configExpectedMod) {
configExpectedMod = config.getModificationCount();
2014-11-24 17:41:04 +01:00
2013-12-29 11:58:54 +01:00
// Update the debug flag
protocolManager.setDebug(config.isDebug());
}
}
2014-11-24 17:41:04 +01:00
private void checkUpdates() {
// Ignore milliseconds - it's pointless
long currentTime = System.currentTimeMillis() / MILLI_PER_SECOND;
try {
long updateTime = config.getAutoLastTime() + config.getAutoDelay();
// Should we update?
2016-04-02 20:47:54 +02:00
if (currentTime > updateTime && !updater.isChecking()) {
// Initiate the update as if it came from the console
if (config.isAutoDownload())
commandProtocol.updateVersion(getServer().getConsoleSender(), false);
else if (config.isAutoNotify())
commandProtocol.checkVersion(getServer().getConsoleSender(), false);
2016-04-02 20:47:54 +02:00
else
commandProtocol.updateFinished();
}
} catch (Exception e) {
reporter.reportDetailed(this, Report.newBuilder(REPORT_CANNOT_UPDATE_PLUGIN).error(e));
UPDATES_DISABLED = true;
}
}
@Override
public void onDisable() {
if (skipDisable) {
return;
}
2014-11-24 17:41:04 +01:00
// Disable compiler
if (backgroundCompiler != null) {
backgroundCompiler.shutdownAll();
backgroundCompiler = null;
BackgroundCompiler.setInstance(null);
}
2014-11-24 17:41:04 +01:00
// Clean up
2013-12-29 11:58:54 +01:00
if (packetTask >= 0) {
getServer().getScheduler().cancelTask(packetTask);
packetTask = -1;
}
2014-11-24 17:41:04 +01:00
2012-11-20 06:48:05 +01:00
// And redirect handler too
if (redirectHandler != null) {
logger.removeHandler(redirectHandler);
}
2014-11-24 17:41:04 +01:00
if (protocolManager != null)
protocolManager.close();
else
return; // Plugin reloaders!
2014-11-24 17:41:04 +01:00
if (unhookTask != null)
unhookTask.close();
protocolManager = null;
2014-11-24 17:41:04 +01:00
statistics = null;
// To clean up global parameters
reporter = new BasicErrorReporter();
}
2014-11-24 17:41:04 +01:00
/**
* Retrieve the metrics instance used to measure users of this library.
* <p>
* Note that this method may return NULL when the server is reloading or shutting down. It is also
* NULL if metrics has been disabled.
* @return Metrics instance container.
*/
public Statistics getStatistics() {
2014-11-24 17:41:04 +01:00
return statistics;
}
2017-10-08 22:02:10 +02:00
public ProtocolConfig getProtocolConfig() {
return config;
}
}