mirror of
https://github.com/dmulloy2/ProtocolLib.git
synced 2024-12-26 11:08:12 +01:00
Add a better error reporter.
This commit is contained in:
parent
5e036185b8
commit
2239c1ea32
@ -4,7 +4,7 @@
|
||||
<groupId>com.comphenix.protocol</groupId>
|
||||
<artifactId>ProtocolLib</artifactId>
|
||||
<name>ProtocolLib</name>
|
||||
<version>1.4.4-SNAPSHOT</version>
|
||||
<version>1.5.0</version>
|
||||
<description>Provides read/write access to the Minecraft protocol.</description>
|
||||
<url>http://dev.bukkit.org/server-mods/protocollib/</url>
|
||||
<developers>
|
||||
|
@ -18,11 +18,11 @@
|
||||
package com.comphenix.protocol;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import com.comphenix.protocol.async.AsyncListenerHandler;
|
||||
import com.comphenix.protocol.error.ErrorReporter;
|
||||
import com.comphenix.protocol.events.PacketEvent;
|
||||
import com.comphenix.protocol.events.PacketListener;
|
||||
|
||||
@ -81,10 +81,10 @@ public interface AsynchronousManager {
|
||||
public abstract PacketStream getPacketStream();
|
||||
|
||||
/**
|
||||
* Retrieve the default error logger.
|
||||
* @return Default logger.
|
||||
* Retrieve the default error reporter.
|
||||
* @return Default reporter.
|
||||
*/
|
||||
public abstract Logger getLogger();
|
||||
public abstract ErrorReporter getErrorReporter();
|
||||
|
||||
/**
|
||||
* Remove listeners, close threads and transmit every delayed packet.
|
||||
|
@ -4,10 +4,9 @@ import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.comphenix.protocol.async.AsyncListenerHandler;
|
||||
import com.comphenix.protocol.error.ErrorReporter;
|
||||
import com.comphenix.protocol.events.ListeningWhitelist;
|
||||
import com.comphenix.protocol.events.PacketContainer;
|
||||
import com.comphenix.protocol.injector.BukkitUnwrapper;
|
||||
@ -30,11 +29,11 @@ import com.comphenix.protocol.reflect.instances.PrimitiveGenerator;
|
||||
class CleanupStaticMembers {
|
||||
|
||||
private ClassLoader loader;
|
||||
private Logger logger;
|
||||
private ErrorReporter reporter;
|
||||
|
||||
public CleanupStaticMembers(ClassLoader loader, Logger logger) {
|
||||
public CleanupStaticMembers(ClassLoader loader, ErrorReporter reporter) {
|
||||
this.loader = loader;
|
||||
this.logger = logger;
|
||||
this.reporter = reporter;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -90,8 +89,8 @@ class CleanupStaticMembers {
|
||||
try {
|
||||
setFinalStatic(field, null);
|
||||
} catch (IllegalAccessException e) {
|
||||
// Just inform us
|
||||
logger.warning("Unable to reset field " + field.getName() + ": " + e.getMessage());
|
||||
// Just inform the player
|
||||
reporter.reportWarning(this, "Unable to reset field " + field.getName() + ": " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -126,7 +125,7 @@ class CleanupStaticMembers {
|
||||
output.add(loader.loadClass(name));
|
||||
} catch (ClassNotFoundException e) {
|
||||
// Warn the user
|
||||
logger.log(Level.WARNING, "Unable to unload class " + name, e);
|
||||
reporter.reportWarning(this, "Unable to unload class " + name, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,6 @@
|
||||
package com.comphenix.protocol;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.bukkit.Server;
|
||||
@ -26,6 +25,8 @@ import org.bukkit.plugin.PluginManager;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import com.comphenix.protocol.async.AsyncFilterManager;
|
||||
import com.comphenix.protocol.error.DetailedErrorReporter;
|
||||
import com.comphenix.protocol.error.ErrorReporter;
|
||||
import com.comphenix.protocol.events.ConnectionSide;
|
||||
import com.comphenix.protocol.events.MonitorAdapter;
|
||||
import com.comphenix.protocol.events.PacketEvent;
|
||||
@ -44,9 +45,12 @@ public class ProtocolLibrary extends JavaPlugin {
|
||||
// There should only be one protocol manager, so we'll make it static
|
||||
private static PacketFilterManager protocolManager;
|
||||
|
||||
// Error logger
|
||||
// Information logger
|
||||
private Logger logger;
|
||||
|
||||
// Error reporter
|
||||
private ErrorReporter reporter;
|
||||
|
||||
// Metrics and statistisc
|
||||
private Statistics statistisc;
|
||||
|
||||
@ -67,39 +71,55 @@ public class ProtocolLibrary extends JavaPlugin {
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
logger = getLoggerSafely();
|
||||
unhookTask = new DelayedSingleTask(this);
|
||||
protocolManager = new PacketFilterManager(getClassLoader(), getServer(), unhookTask, logger);
|
||||
// Add global parameters
|
||||
DetailedErrorReporter reporter = new DetailedErrorReporter();
|
||||
|
||||
try {
|
||||
logger = getLoggerSafely();
|
||||
unhookTask = new DelayedSingleTask(this);
|
||||
protocolManager = new PacketFilterManager(getClassLoader(), getServer(), unhookTask, reporter);
|
||||
reporter.addGlobalParameter("manager", protocolManager);
|
||||
|
||||
} catch (Throwable e) {
|
||||
reporter.reportDetailed(this, "Cannot load ProtocolLib.", e, protocolManager);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
Server server = getServer();
|
||||
PluginManager manager = server.getPluginManager();
|
||||
|
||||
// Initialize background compiler
|
||||
if (backgroundCompiler == null) {
|
||||
backgroundCompiler = new BackgroundCompiler(getClassLoader());
|
||||
BackgroundCompiler.setInstance(backgroundCompiler);
|
||||
}
|
||||
|
||||
// Notify server managers of incompatible plugins
|
||||
checkForIncompatibility(manager);
|
||||
|
||||
// Player login and logout events
|
||||
protocolManager.registerEvents(manager, this);
|
||||
try {
|
||||
Server server = getServer();
|
||||
PluginManager manager = server.getPluginManager();
|
||||
|
||||
// Initialize background compiler
|
||||
if (backgroundCompiler == null) {
|
||||
backgroundCompiler = new BackgroundCompiler(getClassLoader());
|
||||
BackgroundCompiler.setInstance(backgroundCompiler);
|
||||
}
|
||||
|
||||
// Notify server managers of incompatible plugins
|
||||
checkForIncompatibility(manager);
|
||||
|
||||
// Worker that ensures that async packets are eventually sent
|
||||
createAsyncTask(server);
|
||||
//toggleDebugListener();
|
||||
// Player login and logout events
|
||||
protocolManager.registerEvents(manager, this);
|
||||
|
||||
// Worker that ensures that async packets are eventually sent
|
||||
createAsyncTask(server);
|
||||
//toggleDebugListener();
|
||||
|
||||
} catch (Throwable e) {
|
||||
reporter.reportDetailed(this, "Cannot enable ProtocolLib.", e);
|
||||
disablePlugin();
|
||||
return;
|
||||
}
|
||||
|
||||
// Try to enable statistics
|
||||
try {
|
||||
statistisc = new Statistics(this);
|
||||
} catch (IOException e) {
|
||||
logger.log(Level.SEVERE, "Unable to enable metrics.", e);
|
||||
reporter.reportDetailed(this, "Unable to enable metrics.", e, statistisc);
|
||||
} catch (Throwable e) {
|
||||
logger.log(Level.SEVERE, "Metrics cannot be enabled. Incompatible Bukkit version.", e);
|
||||
reporter.reportDetailed(this, "Metrics cannot be enabled. Incompatible Bukkit version.", e, statistisc);
|
||||
}
|
||||
}
|
||||
|
||||
@ -136,6 +156,13 @@ public class ProtocolLibrary extends JavaPlugin {
|
||||
debugListener = !debugListener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable the current plugin.
|
||||
*/
|
||||
private void disablePlugin() {
|
||||
getServer().getPluginManager().disablePlugin(this);
|
||||
}
|
||||
|
||||
private void createAsyncTask(Server server) {
|
||||
try {
|
||||
if (asyncPacketTask >= 0)
|
||||
@ -154,7 +181,7 @@ public class ProtocolLibrary extends JavaPlugin {
|
||||
|
||||
} catch (Throwable e) {
|
||||
if (asyncPacketTask == -1) {
|
||||
logger.log(Level.SEVERE, "Unable to create packet timeout task.", e);
|
||||
reporter.reportDetailed(this, "Unable to create packet timeout task.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -166,7 +193,7 @@ public class ProtocolLibrary extends JavaPlugin {
|
||||
for (String plugin : incompatiblePlugins) {
|
||||
if (manager.getPlugin(plugin) != null) {
|
||||
// Check for versions, ect.
|
||||
logger.severe("Detected incompatible plugin: " + plugin);
|
||||
reporter.reportWarning(this, "Detected incompatible plugin: " + plugin);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -192,7 +219,7 @@ public class ProtocolLibrary extends JavaPlugin {
|
||||
statistisc = null;
|
||||
|
||||
// Leaky ClassLoader begone!
|
||||
CleanupStaticMembers cleanup = new CleanupStaticMembers(getClassLoader(), logger);
|
||||
CleanupStaticMembers cleanup = new CleanupStaticMembers(getClassLoader(), reporter);
|
||||
cleanup.resetAll();
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,6 @@ import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.scheduler.BukkitScheduler;
|
||||
@ -29,6 +28,7 @@ import org.bukkit.scheduler.BukkitScheduler;
|
||||
import com.comphenix.protocol.AsynchronousManager;
|
||||
import com.comphenix.protocol.PacketStream;
|
||||
import com.comphenix.protocol.ProtocolManager;
|
||||
import com.comphenix.protocol.error.ErrorReporter;
|
||||
import com.comphenix.protocol.events.ListeningWhitelist;
|
||||
import com.comphenix.protocol.events.PacketEvent;
|
||||
import com.comphenix.protocol.events.PacketListener;
|
||||
@ -49,7 +49,7 @@ public class AsyncFilterManager implements AsynchronousManager {
|
||||
private PacketProcessingQueue clientProcessingQueue;
|
||||
private PacketSendingQueue clientQueue;
|
||||
|
||||
private Logger logger;
|
||||
private ErrorReporter reporter;
|
||||
|
||||
// The likely main thread
|
||||
private Thread mainThread;
|
||||
@ -66,7 +66,7 @@ public class AsyncFilterManager implements AsynchronousManager {
|
||||
// Whether or not we're currently cleaning up
|
||||
private volatile boolean cleaningUp;
|
||||
|
||||
public AsyncFilterManager(Logger logger, BukkitScheduler scheduler, ProtocolManager manager) {
|
||||
public AsyncFilterManager(ErrorReporter reporter, BukkitScheduler scheduler, ProtocolManager manager) {
|
||||
|
||||
// Server packets are synchronized already
|
||||
this.serverQueue = new PacketSendingQueue(false);
|
||||
@ -80,7 +80,7 @@ public class AsyncFilterManager implements AsynchronousManager {
|
||||
this.scheduler = scheduler;
|
||||
this.manager = manager;
|
||||
|
||||
this.logger = logger;
|
||||
this.reporter = reporter;
|
||||
this.mainThread = Thread.currentThread();
|
||||
}
|
||||
|
||||
@ -267,10 +267,10 @@ public class AsyncFilterManager implements AsynchronousManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Logger getLogger() {
|
||||
return logger;
|
||||
public ErrorReporter getErrorReporter() {
|
||||
return reporter;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void cleanupAll() {
|
||||
cleaningUp = true;
|
||||
|
@ -442,8 +442,7 @@ public class AsyncListenerHandler {
|
||||
|
||||
} catch (Throwable e) {
|
||||
// Minecraft doesn't want your Exception.
|
||||
filterManager.getLogger().log(Level.SEVERE,
|
||||
"Unhandled exception occured in onAsyncPacket() for " + getPluginName(), e);
|
||||
filterManager.getErrorReporter().reportMinimal(listener.getPlugin(), "onAsyncPacket()", e);
|
||||
}
|
||||
|
||||
// Now, get the next non-cancelled listener
|
||||
|
@ -0,0 +1,268 @@
|
||||
package com.comphenix.protocol.error;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.apache.commons.lang.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang.builder.ToStringStyle;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import com.comphenix.protocol.events.PacketAdapter;
|
||||
import com.google.common.primitives.Primitives;
|
||||
|
||||
/**
|
||||
* Internal class used to handle exceptions.
|
||||
*
|
||||
* @author Kristian
|
||||
*/
|
||||
public class DetailedErrorReporter implements ErrorReporter {
|
||||
|
||||
public static final String SECOND_LEVEL_PREFIX = " ";
|
||||
public static final String DEFAULT_PREFIX = " ";
|
||||
public static final String DEFAULT_SUPPORT_URL = "http://dev.bukkit.org/server-mods/protocollib/";
|
||||
public static final String PLUGIN_NAME = "ProtocolLib";
|
||||
|
||||
// We don't want to spam the server
|
||||
public static final int DEFAULT_MAX_ERROR_COUNT = 20;
|
||||
|
||||
protected String prefix;
|
||||
protected String supportURL;
|
||||
|
||||
protected int errorCount;
|
||||
protected int maxErrorCount;
|
||||
protected Logger logger;
|
||||
|
||||
// Whether or not Apache Commons is not present
|
||||
protected boolean apacheCommonsMissing;
|
||||
|
||||
// Map of global objects
|
||||
protected Map<String, Object> globalParameters = new HashMap<String, Object>();
|
||||
|
||||
/**
|
||||
* Create a default error reporting system.
|
||||
*/
|
||||
public DetailedErrorReporter() {
|
||||
this(DEFAULT_PREFIX, DEFAULT_SUPPORT_URL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a central error reporting system.
|
||||
* @param prefix - default line prefix.
|
||||
* @param supportURL - URL to report the error.
|
||||
*/
|
||||
public DetailedErrorReporter(String prefix, String supportURL) {
|
||||
this(prefix, supportURL, DEFAULT_MAX_ERROR_COUNT, getBukkitLogger());
|
||||
}
|
||||
|
||||
// Attempt to get the logger.
|
||||
private static Logger getBukkitLogger() {
|
||||
try {
|
||||
return Bukkit.getLogger();
|
||||
} catch (Throwable e) {
|
||||
return Logger.getLogger("Minecraft");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a central error reporting system.
|
||||
* @param prefix - default line prefix.
|
||||
* @param supportURL - URL to report the error.
|
||||
* @param maxErrorCount - number of errors to print before giving up.
|
||||
* @param logger - current logger.
|
||||
*/
|
||||
public DetailedErrorReporter(String prefix, String supportURL, int maxErrorCount, Logger logger) {
|
||||
this.prefix = prefix;
|
||||
this.supportURL = supportURL;
|
||||
this.maxErrorCount = maxErrorCount;
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reportMinimal(Plugin sender, String methodName, Throwable error) {
|
||||
logger.log(Level.SEVERE, "[" + PLUGIN_NAME + "] Unhandled exception occured in " + methodName + " for " +
|
||||
PacketAdapter.getPluginName(sender), error);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reportWarning(Object sender, String message) {
|
||||
logger.log(Level.WARNING, "[" + PLUGIN_NAME + "] [" + getSenderName(sender) + "] " + message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reportWarning(Object sender, String message, Throwable error) {
|
||||
logger.log(Level.WARNING, "[" + PLUGIN_NAME + "] [" + getSenderName(sender) + "] " + message, error);
|
||||
}
|
||||
|
||||
private String getSenderName(Object sender) {
|
||||
if (sender != null)
|
||||
return sender.getClass().getSimpleName();
|
||||
else
|
||||
return "NULL";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reportDetailed(Object sender, String message, Throwable error, Object... parameters) {
|
||||
|
||||
// Do not overtly spam the server!
|
||||
if (++errorCount > maxErrorCount) {
|
||||
String maxReached = String.format("Reached maxmimum error count. Cannot pass error %s from %s.", error, sender);
|
||||
logger.severe(maxReached);
|
||||
return;
|
||||
}
|
||||
|
||||
StringWriter text = new StringWriter();
|
||||
PrintWriter writer = new PrintWriter(text);
|
||||
|
||||
// Helpful message
|
||||
writer.println("[ProtocolLib] INTERNAL ERROR: " + message);
|
||||
writer.println("If this problem hasn't already been reported, please open a ticket");
|
||||
writer.println("at " + supportURL + " with the following data:");
|
||||
|
||||
// Now, let us print important exception information
|
||||
writer.println(" ===== STACK TRACE =====");
|
||||
|
||||
if (error != null)
|
||||
error.printStackTrace(writer);
|
||||
|
||||
// Data dump!
|
||||
writer.println(" ===== DUMP =====");
|
||||
|
||||
// Relevant parameters
|
||||
if (parameters != null && parameters.length > 0) {
|
||||
writer.println("Parameters:");
|
||||
|
||||
// We *really* want to get as much information as possible
|
||||
for (Object param : parameters) {
|
||||
writer.println(addPrefix(getStringDescription(param), SECOND_LEVEL_PREFIX));
|
||||
}
|
||||
}
|
||||
|
||||
// Global parameters
|
||||
for (String param : globalParameters()) {
|
||||
writer.println(SECOND_LEVEL_PREFIX + param + ":");
|
||||
writer.println(addPrefix(getStringDescription(getGlobalParameter(param)),
|
||||
SECOND_LEVEL_PREFIX + SECOND_LEVEL_PREFIX));
|
||||
}
|
||||
|
||||
// Now, for the sender itself
|
||||
writer.println("Sender:");
|
||||
writer.println(addPrefix(getStringDescription(sender), SECOND_LEVEL_PREFIX));
|
||||
|
||||
// Add the server version too
|
||||
if (Bukkit.getServer() != null) {
|
||||
writer.println("Server:");
|
||||
writer.println(addPrefix(Bukkit.getServer().getVersion(), SECOND_LEVEL_PREFIX));
|
||||
}
|
||||
|
||||
// Make sure it is reported
|
||||
logger.severe(addPrefix(text.toString(), prefix));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given prefix to every line in the text.
|
||||
* @param text - text to modify.
|
||||
* @param prefix - prefix added to every line in the text.
|
||||
* @return The modified text.
|
||||
*/
|
||||
protected String addPrefix(String text, String prefix) {
|
||||
return text.replaceAll("(?m)^", prefix);
|
||||
}
|
||||
|
||||
protected String getStringDescription(Object value) {
|
||||
|
||||
// We can't only rely on toString.
|
||||
if (value == null) {
|
||||
return "[NULL]";
|
||||
} if (isSimpleType(value)) {
|
||||
return value.toString();
|
||||
} else {
|
||||
try {
|
||||
if (!apacheCommonsMissing)
|
||||
return (ToStringBuilder.reflectionToString(value, ToStringStyle.MULTI_LINE_STYLE, false, null));
|
||||
} catch (Throwable ex) {
|
||||
// Apache is probably missing
|
||||
logger.warning("Cannot find Apache Commons. Object introspection disabled.");
|
||||
apacheCommonsMissing = true;
|
||||
}
|
||||
|
||||
// Just use toString()
|
||||
return String.format("%s", value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given object is a wrapper for a primitive/simple type or not.
|
||||
* @param test - the object to test.
|
||||
* @return TRUE if this object is simple enough to simply be printed, FALSE othewise.
|
||||
*/
|
||||
protected boolean isSimpleType(Object test) {
|
||||
return test instanceof String || Primitives.isWrapperType(test.getClass());
|
||||
}
|
||||
|
||||
public int getErrorCount() {
|
||||
return errorCount;
|
||||
}
|
||||
|
||||
public void setErrorCount(int errorCount) {
|
||||
this.errorCount = errorCount;
|
||||
}
|
||||
|
||||
public int getMaxErrorCount() {
|
||||
return maxErrorCount;
|
||||
}
|
||||
|
||||
public void setMaxErrorCount(int maxErrorCount) {
|
||||
this.maxErrorCount = maxErrorCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given global parameter. It will be included in every error report.
|
||||
* @param key - name of parameter.
|
||||
* @param value - the global parameter itself.
|
||||
*/
|
||||
public void addGlobalParameter(String key, Object value) {
|
||||
globalParameters.put(key, value);
|
||||
}
|
||||
|
||||
public Object getGlobalParameter(String key) {
|
||||
return globalParameters.get(key);
|
||||
}
|
||||
|
||||
public void clearGlobalParameters() {
|
||||
globalParameters.clear();
|
||||
}
|
||||
|
||||
public Set<String> globalParameters() {
|
||||
return globalParameters.keySet();
|
||||
}
|
||||
|
||||
public String getSupportURL() {
|
||||
return supportURL;
|
||||
}
|
||||
|
||||
public void setSupportURL(String supportURL) {
|
||||
this.supportURL = supportURL;
|
||||
}
|
||||
|
||||
public String getPrefix() {
|
||||
return prefix;
|
||||
}
|
||||
|
||||
public void setPrefix(String prefix) {
|
||||
this.prefix = prefix;
|
||||
}
|
||||
|
||||
public Logger getLogger() {
|
||||
return logger;
|
||||
}
|
||||
|
||||
public void setLogger(Logger logger) {
|
||||
this.logger = logger;
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
package com.comphenix.protocol.error;
|
||||
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
public interface ErrorReporter {
|
||||
|
||||
/**
|
||||
* Prints a small minimal error report about an exception from another plugin.
|
||||
* @param sender - the other plugin.
|
||||
* @param methodName - name of the caller method.
|
||||
* @param error - the exception itself.
|
||||
*/
|
||||
public abstract void reportMinimal(Plugin sender, String methodName, Throwable error);
|
||||
|
||||
/**
|
||||
* Prints a warning message from the current plugin.
|
||||
* @param sender - the object containing the caller method.
|
||||
* @param message - error message.
|
||||
*/
|
||||
public abstract void reportWarning(Object sender, String message);
|
||||
|
||||
/**
|
||||
* Prints a warning message from the current plugin.
|
||||
* @param sender - the object containing the caller method.
|
||||
* @param message - error message.
|
||||
* @param error - the exception that was thrown.
|
||||
*/
|
||||
public abstract void reportWarning(Object sender, String message, Throwable error);
|
||||
|
||||
/**
|
||||
* Prints a detailed error report about an unhandled exception.
|
||||
* @param sender - the object containing the caller method.
|
||||
* @param message - an error message to include.
|
||||
* @param error - the exception that was thrown in the caller method.
|
||||
* @param parameters - parameters from the caller method.
|
||||
*/
|
||||
public abstract void reportDetailed(Object sender, String message, Throwable error, Object... parameters);
|
||||
|
||||
}
|
@ -168,12 +168,20 @@ public abstract class PacketAdapter implements PacketListener {
|
||||
|
||||
/**
|
||||
* Retrieves the name of the plugin that has been associated with the listener.
|
||||
* @param listener - the listener.
|
||||
* @return Name of the associated plugin.
|
||||
*/
|
||||
public static String getPluginName(PacketListener listener) {
|
||||
|
||||
Plugin plugin = listener.getPlugin();
|
||||
|
||||
return getPluginName(listener.getPlugin());
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the name of the given plugin.
|
||||
* @param plugin - the plugin.
|
||||
* @return Name of the given plugin.
|
||||
*/
|
||||
public static String getPluginName(Plugin plugin) {
|
||||
|
||||
// Try to get the plugin name
|
||||
try {
|
||||
if (plugin == null)
|
||||
|
@ -25,8 +25,6 @@ import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@ -51,6 +49,8 @@ import com.comphenix.protocol.AsynchronousManager;
|
||||
import com.comphenix.protocol.ProtocolManager;
|
||||
import com.comphenix.protocol.async.AsyncFilterManager;
|
||||
import com.comphenix.protocol.async.AsyncMarker;
|
||||
import com.comphenix.protocol.error.DetailedErrorReporter;
|
||||
import com.comphenix.protocol.error.ErrorReporter;
|
||||
import com.comphenix.protocol.events.*;
|
||||
import com.comphenix.protocol.injector.player.PlayerInjectionHandler;
|
||||
import com.comphenix.protocol.reflect.FieldAccessException;
|
||||
@ -118,8 +118,8 @@ public final class PacketFilterManager implements ProtocolManager, ListenerInvok
|
||||
// The default class loader
|
||||
private ClassLoader classLoader;
|
||||
|
||||
// Error logger
|
||||
private Logger logger;
|
||||
// Error repoter
|
||||
private ErrorReporter reporter;
|
||||
|
||||
// The current server
|
||||
private Server server;
|
||||
@ -142,9 +142,9 @@ public final class PacketFilterManager implements ProtocolManager, ListenerInvok
|
||||
* Only create instances of this class if protocol lib is disabled.
|
||||
* @param unhookTask
|
||||
*/
|
||||
public PacketFilterManager(ClassLoader classLoader, Server server, DelayedSingleTask unhookTask, Logger logger) {
|
||||
if (logger == null)
|
||||
throw new IllegalArgumentException("logger cannot be NULL.");
|
||||
public PacketFilterManager(ClassLoader classLoader, Server server, DelayedSingleTask unhookTask, DetailedErrorReporter reporter) {
|
||||
if (reporter == null)
|
||||
throw new IllegalArgumentException("reporter cannot be NULL.");
|
||||
if (classLoader == null)
|
||||
throw new IllegalArgumentException("classLoader cannot be NULL.");
|
||||
|
||||
@ -155,7 +155,7 @@ public final class PacketFilterManager implements ProtocolManager, ListenerInvok
|
||||
this.unhookTask = unhookTask;
|
||||
this.server = server;
|
||||
this.classLoader = classLoader;
|
||||
this.logger = logger;
|
||||
this.reporter = reporter;
|
||||
|
||||
// Used to determine if injection is needed
|
||||
Predicate<GamePhase> isInjectionNecessary = new Predicate<GamePhase>() {
|
||||
@ -174,20 +174,20 @@ public final class PacketFilterManager implements ProtocolManager, ListenerInvok
|
||||
|
||||
try {
|
||||
// Initialize injection mangers
|
||||
this.playerInjection = new PlayerInjectionHandler(classLoader, logger, isInjectionNecessary, this, server);
|
||||
this.playerInjection = new PlayerInjectionHandler(classLoader, reporter, isInjectionNecessary, this, server);
|
||||
this.packetInjector = new PacketInjector(classLoader, this, playerInjection);
|
||||
this.asyncFilterManager = new AsyncFilterManager(logger, server.getScheduler(), this);
|
||||
this.asyncFilterManager = new AsyncFilterManager(reporter, server.getScheduler(), this);
|
||||
|
||||
// Attempt to load the list of server and client packets
|
||||
try {
|
||||
this.serverPackets = MinecraftRegistry.getServerPackets();
|
||||
this.clientPackets = MinecraftRegistry.getClientPackets();
|
||||
} catch (FieldAccessException e) {
|
||||
logger.log(Level.WARNING, "Cannot load server and client packet list.", e);
|
||||
reporter.reportWarning(this, "Cannot load server and client packet list.", e);
|
||||
}
|
||||
|
||||
} catch (IllegalAccessException e) {
|
||||
logger.log(Level.SEVERE, "Unable to initialize packet injector.", e);
|
||||
reporter.reportWarning(this, "Unable to initialize packet injector.", e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -215,10 +215,6 @@ public final class PacketFilterManager implements ProtocolManager, ListenerInvok
|
||||
playerInjection.checkListener(packetListeners);
|
||||
}
|
||||
|
||||
public Logger getLogger() {
|
||||
return logger;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImmutableSet<PacketListener> getPacketListeners() {
|
||||
return ImmutableSet.copyOf(packetListeners);
|
||||
@ -398,9 +394,9 @@ public final class PacketFilterManager implements ProtocolManager, ListenerInvok
|
||||
|
||||
// Process synchronous events
|
||||
if (sending)
|
||||
packetListeners.invokePacketSending(logger, event);
|
||||
packetListeners.invokePacketSending(reporter, event);
|
||||
else
|
||||
packetListeners.invokePacketRecieving(logger, event);
|
||||
packetListeners.invokePacketRecieving(reporter, event);
|
||||
|
||||
// To cancel asynchronous processing, use the async marker
|
||||
if (!event.isCancelled() && !hasAsyncCancelled(event.getAsyncMarker())) {
|
||||
@ -438,7 +434,7 @@ public final class PacketFilterManager implements ProtocolManager, ListenerInvok
|
||||
if (serverPackets != null && serverPackets.contains(packetID))
|
||||
playerInjection.addPacketHandler(packetID);
|
||||
else
|
||||
logger.warning(String.format(
|
||||
reporter.reportWarning(this, String.format(
|
||||
"[%s] Unsupported server packet ID in current Minecraft version: %s",
|
||||
PacketAdapter.getPluginName(listener), packetID
|
||||
));
|
||||
@ -449,7 +445,7 @@ public final class PacketFilterManager implements ProtocolManager, ListenerInvok
|
||||
if (clientPackets != null && clientPackets.contains(packetID))
|
||||
packetInjector.addPacketHandler(packetID);
|
||||
else
|
||||
logger.warning(String.format(
|
||||
reporter.reportWarning(this, String.format(
|
||||
"[%s] Unsupported client packet ID in current Minecraft version: %s",
|
||||
PacketAdapter.getPluginName(listener), packetID
|
||||
));
|
||||
|
@ -18,11 +18,9 @@
|
||||
package com.comphenix.protocol.injector;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.comphenix.protocol.concurrency.AbstractConcurrentListenerMultimap;
|
||||
import com.comphenix.protocol.events.PacketAdapter;
|
||||
import com.comphenix.protocol.error.ErrorReporter;
|
||||
import com.comphenix.protocol.events.PacketEvent;
|
||||
import com.comphenix.protocol.events.PacketListener;
|
||||
|
||||
@ -35,10 +33,10 @@ class SortedPacketListenerList extends AbstractConcurrentListenerMultimap<Packet
|
||||
|
||||
/**
|
||||
* Invokes the given packet event for every registered listener.
|
||||
* @param logger - the logger that will be used to inform about listener exceptions.
|
||||
* @param reporter - the error reporter that will be used to inform about listener exceptions.
|
||||
* @param event - the packet event to invoke.
|
||||
*/
|
||||
public void invokePacketRecieving(Logger logger, PacketEvent event) {
|
||||
public void invokePacketRecieving(ErrorReporter reporter, PacketEvent event) {
|
||||
Collection<PrioritizedListener<PacketListener>> list = getListener(event.getPacketID());
|
||||
|
||||
if (list == null)
|
||||
@ -50,19 +48,17 @@ class SortedPacketListenerList extends AbstractConcurrentListenerMultimap<Packet
|
||||
element.getListener().onPacketReceiving(event);
|
||||
} catch (Throwable e) {
|
||||
// Minecraft doesn't want your Exception.
|
||||
logger.log(Level.SEVERE,
|
||||
"Exception occured in onPacketReceiving() for " +
|
||||
PacketAdapter.getPluginName(element.getListener()), e);
|
||||
reporter.reportMinimal(element.getListener().getPlugin(), "onPacketReceiving()", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes the given packet event for every registered listener.
|
||||
* @param logger - the logger that will be used to inform about listener exceptions.
|
||||
* @param reporter - the error reporter that will be used to inform about listener exceptions.
|
||||
* @param event - the packet event to invoke.
|
||||
*/
|
||||
public void invokePacketSending(Logger logger, PacketEvent event) {
|
||||
public void invokePacketSending(ErrorReporter reporter, PacketEvent event) {
|
||||
Collection<PrioritizedListener<PacketListener>> list = getListener(event.getPacketID());
|
||||
|
||||
if (list == null)
|
||||
@ -73,9 +69,7 @@ class SortedPacketListenerList extends AbstractConcurrentListenerMultimap<Packet
|
||||
element.getListener().onPacketSending(event);
|
||||
} catch (Throwable e) {
|
||||
// Minecraft doesn't want your Exception.
|
||||
logger.log(Level.SEVERE,
|
||||
"Exception occured in onPacketSending() for " +
|
||||
PacketAdapter.getPluginName(element.getListener()), e);
|
||||
reporter.reportMinimal(element.getListener().getPlugin(), "onPacketSending()", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,14 +21,13 @@ import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import net.minecraft.server.NetLoginHandler;
|
||||
import net.sf.cglib.proxy.Factory;
|
||||
|
||||
import org.bukkit.Server;
|
||||
|
||||
import com.comphenix.protocol.error.ErrorReporter;
|
||||
import com.comphenix.protocol.reflect.FieldUtils;
|
||||
import com.comphenix.protocol.reflect.FuzzyReflection;
|
||||
import com.comphenix.protocol.reflect.ObjectCloner;
|
||||
@ -55,16 +54,16 @@ class InjectedServerConnection {
|
||||
private NetLoginInjector netLoginInjector;
|
||||
|
||||
private Server server;
|
||||
private Logger logger;
|
||||
private ErrorReporter reporter;
|
||||
private boolean hasAttempted;
|
||||
private boolean hasSuccess;
|
||||
|
||||
private Object minecraftServer = null;
|
||||
|
||||
public InjectedServerConnection(Logger logger, Server server, NetLoginInjector netLoginInjector) {
|
||||
public InjectedServerConnection(ErrorReporter reporter, Server server, NetLoginInjector netLoginInjector) {
|
||||
this.listFields = new ArrayList<VolatileField>();
|
||||
this.replacedLists = new ArrayList<ReplacedArrayList<Object>>();
|
||||
this.logger = logger;
|
||||
this.reporter = reporter;
|
||||
this.server = server;
|
||||
this.netLoginInjector = netLoginInjector;
|
||||
}
|
||||
@ -83,7 +82,7 @@ class InjectedServerConnection {
|
||||
try {
|
||||
minecraftServer = FieldUtils.readField(minecraftServerField, server, true);
|
||||
} catch (IllegalAccessException e1) {
|
||||
logger.log(Level.WARNING, "Cannot extract minecraft server from Bukkit.");
|
||||
reporter.reportWarning(this, "Cannot extract minecraft server from Bukkit.");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -95,15 +94,13 @@ class InjectedServerConnection {
|
||||
injectServerConnection();
|
||||
|
||||
} catch (IllegalArgumentException e) {
|
||||
// DEBUG
|
||||
logger.log(Level.WARNING, "Reverting to old 1.2.5 server connection injection.", e);
|
||||
|
||||
|
||||
// Minecraft 1.2.5 or lower
|
||||
injectListenerThread();
|
||||
|
||||
} catch (Exception e) {
|
||||
// Oh damn - inform the player
|
||||
logger.log(Level.SEVERE, "Cannot inject into server connection. Bad things will happen.", e);
|
||||
reporter.reportDetailed(this, "Cannot inject into server connection. Bad things will happen.", e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -115,7 +112,7 @@ class InjectedServerConnection {
|
||||
listenerThreadField = FuzzyReflection.fromObject(minecraftServer).
|
||||
getFieldByType(".*NetworkListenThread");
|
||||
} catch (RuntimeException e) {
|
||||
logger.log(Level.SEVERE, "Cannot find listener thread in MinecraftServer.", e);
|
||||
reporter.reportDetailed(this, "Cannot find listener thread in MinecraftServer.", e, minecraftServer);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -125,7 +122,7 @@ class InjectedServerConnection {
|
||||
try {
|
||||
listenerThread = listenerThreadField.get(minecraftServer);
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.WARNING, "Unable to read the listener thread.", e);
|
||||
reporter.reportWarning(this, "Unable to read the listener thread.", e);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -142,7 +139,7 @@ class InjectedServerConnection {
|
||||
try {
|
||||
serverConnection = serverConnectionMethod.invoke(minecraftServer);
|
||||
} catch (Exception ex) {
|
||||
logger.log(Level.WARNING, "Unable to retrieve server connection", ex);
|
||||
reporter.reportDetailed(this, "Unable to retrieve server connection", ex, minecraftServer);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -154,7 +151,7 @@ class InjectedServerConnection {
|
||||
|
||||
// Verify the field count
|
||||
if (matches.size() != 1)
|
||||
logger.log(Level.WARNING, "Unexpected number of threads in " + serverConnection.getClass().getName());
|
||||
reporter.reportWarning(this, "Unexpected number of threads in " + serverConnection.getClass().getName());
|
||||
else
|
||||
dedicatedThreadField = matches.get(0);
|
||||
}
|
||||
@ -164,7 +161,7 @@ class InjectedServerConnection {
|
||||
if (dedicatedThreadField != null)
|
||||
injectEveryListField(FieldUtils.readField(dedicatedThreadField, serverConnection, true), 1);
|
||||
} catch (IllegalAccessException e) {
|
||||
logger.log(Level.WARNING, "Unable to retrieve net handler thread.", e);
|
||||
reporter.reportWarning(this, "Unable to retrieve net handler thread.", e);
|
||||
}
|
||||
|
||||
injectIntoList(serverConnection, listField);
|
||||
@ -186,7 +183,7 @@ class InjectedServerConnection {
|
||||
|
||||
// Warn about unexpected errors
|
||||
if (lists.size() < minimum) {
|
||||
logger.log(Level.WARNING, "Unable to inject " + minimum + " lists in " + container.getClass().getName());
|
||||
reporter.reportWarning(this, "Unable to inject " + minimum + " lists in " + container.getClass().getName());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,12 +4,11 @@ import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReadWriteLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.comphenix.protocol.error.ErrorReporter;
|
||||
import com.comphenix.protocol.injector.GamePhase;
|
||||
import com.comphenix.protocol.injector.player.TemporaryPlayerFactory.InjectContainer;
|
||||
import com.google.common.collect.Maps;
|
||||
@ -27,16 +26,16 @@ class NetLoginInjector {
|
||||
private PlayerInjectionHandler injectionHandler;
|
||||
private Server server;
|
||||
|
||||
// The current logger
|
||||
private Logger logger;
|
||||
// The current error rerporter
|
||||
private ErrorReporter reporter;
|
||||
|
||||
private ReadWriteLock injectionLock = new ReentrantReadWriteLock();
|
||||
|
||||
// Used to create fake players
|
||||
private TemporaryPlayerFactory tempPlayerFactory = new TemporaryPlayerFactory();
|
||||
|
||||
public NetLoginInjector(Logger logger, PlayerInjectionHandler injectionHandler, Server server) {
|
||||
this.logger = logger;
|
||||
public NetLoginInjector(ErrorReporter reporter, PlayerInjectionHandler injectionHandler, Server server) {
|
||||
this.reporter = reporter;
|
||||
this.injectionHandler = injectionHandler;
|
||||
this.server = server;
|
||||
}
|
||||
@ -71,7 +70,7 @@ class NetLoginInjector {
|
||||
|
||||
} catch (Throwable e) {
|
||||
// Minecraft can't handle this, so we'll deal with it here
|
||||
logger.log(Level.WARNING, "Unable to hook NetLoginHandler.", e);
|
||||
reporter.reportDetailed(this, "Unable to hook NetLoginHandler.", e, inserting);
|
||||
return inserting;
|
||||
|
||||
} finally {
|
||||
|
@ -24,11 +24,11 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.comphenix.protocol.Packets;
|
||||
import com.comphenix.protocol.error.ErrorReporter;
|
||||
import com.comphenix.protocol.events.ListeningWhitelist;
|
||||
import com.comphenix.protocol.events.PacketListener;
|
||||
import com.comphenix.protocol.injector.GamePhase;
|
||||
@ -73,10 +73,10 @@ class NetworkFieldInjector extends PlayerInjector {
|
||||
// Used to construct proxy objects
|
||||
private ClassLoader classLoader;
|
||||
|
||||
public NetworkFieldInjector(ClassLoader classLoader, Logger logger, Player player,
|
||||
public NetworkFieldInjector(ClassLoader classLoader, ErrorReporter reporter, Player player,
|
||||
ListenerInvoker manager, IntegerSet sendingFilters) throws IllegalAccessException {
|
||||
|
||||
super(logger, player, manager);
|
||||
super(reporter, player, manager);
|
||||
this.classLoader = classLoader;
|
||||
this.sendingFilters = sendingFilters;
|
||||
}
|
||||
|
@ -28,11 +28,11 @@ import net.sf.cglib.proxy.MethodInterceptor;
|
||||
import net.sf.cglib.proxy.MethodProxy;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.comphenix.protocol.Packets;
|
||||
import com.comphenix.protocol.error.ErrorReporter;
|
||||
import com.comphenix.protocol.events.ListeningWhitelist;
|
||||
import com.comphenix.protocol.events.PacketListener;
|
||||
import com.comphenix.protocol.injector.GamePhase;
|
||||
@ -54,9 +54,9 @@ class NetworkObjectInjector extends PlayerInjector {
|
||||
// Shared callback filter - avoid creating a new class every time
|
||||
private static CallbackFilter callbackFilter;
|
||||
|
||||
public NetworkObjectInjector(ClassLoader classLoader, Logger logger, Player player,
|
||||
public NetworkObjectInjector(ClassLoader classLoader, ErrorReporter reporter, Player player,
|
||||
ListenerInvoker invoker, IntegerSet sendingFilters) throws IllegalAccessException {
|
||||
super(logger, player, invoker);
|
||||
super(reporter, player, invoker);
|
||||
this.sendingFilters = sendingFilters;
|
||||
this.classLoader = classLoader;
|
||||
}
|
||||
|
@ -20,8 +20,6 @@ package com.comphenix.protocol.injector.player;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import net.minecraft.server.Packet;
|
||||
import net.sf.cglib.proxy.Callback;
|
||||
@ -34,6 +32,7 @@ import net.sf.cglib.proxy.NoOp;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.comphenix.protocol.error.ErrorReporter;
|
||||
import com.comphenix.protocol.events.PacketListener;
|
||||
import com.comphenix.protocol.injector.GamePhase;
|
||||
import com.comphenix.protocol.injector.ListenerInvoker;
|
||||
@ -68,11 +67,11 @@ public class NetworkServerInjector extends PlayerInjector {
|
||||
private boolean hasDisconnected;
|
||||
|
||||
public NetworkServerInjector(
|
||||
ClassLoader classLoader, Logger logger, Player player,
|
||||
ClassLoader classLoader, ErrorReporter reporter, Player player,
|
||||
ListenerInvoker invoker, IntegerSet sendingFilters,
|
||||
InjectedServerConnection serverInjection) throws IllegalAccessException {
|
||||
|
||||
super(logger, player, invoker);
|
||||
super(reporter, player, invoker);
|
||||
this.classLoader = classLoader;
|
||||
this.sendingFilters = sendingFilters;
|
||||
this.serverInjection = serverInjection;
|
||||
@ -295,9 +294,9 @@ public class NetworkServerInjector extends PlayerInjector {
|
||||
FieldUtils.writeField(disconnectField, handler, value);
|
||||
|
||||
} catch (IllegalArgumentException e) {
|
||||
logger.log(Level.WARNING, "Unable to find disconnect field. Is ProtocolLib up to date?");
|
||||
reporter.reportDetailed(this, "Unable to find disconnect field. Is ProtocolLib up to date?", e, handler);
|
||||
} catch (IllegalAccessException e) {
|
||||
logger.log(Level.WARNING, "Unable to update disconnected field. Player quit event may be sent twice.");
|
||||
reporter.reportWarning(this, "Unable to update disconnected field. Player quit event may be sent twice.");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,14 +24,13 @@ import java.net.Socket;
|
||||
import java.net.SocketAddress;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import net.minecraft.server.Packet;
|
||||
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.comphenix.protocol.error.ErrorReporter;
|
||||
import com.comphenix.protocol.events.PacketAdapter;
|
||||
import com.comphenix.protocol.events.PacketContainer;
|
||||
import com.comphenix.protocol.events.PacketListener;
|
||||
@ -72,8 +71,8 @@ public class PlayerInjectionHandler {
|
||||
private volatile PlayerInjectHooks loginPlayerHook = PlayerInjectHooks.NETWORK_SERVER_OBJECT;
|
||||
private volatile PlayerInjectHooks playingPlayerHook = PlayerInjectHooks.NETWORK_SERVER_OBJECT;
|
||||
|
||||
// Error logger
|
||||
private Logger logger;
|
||||
// Error reporter
|
||||
private ErrorReporter reporter;
|
||||
|
||||
// Whether or not we're closing
|
||||
private boolean hasClosed;
|
||||
@ -90,15 +89,15 @@ public class PlayerInjectionHandler {
|
||||
// Used to filter injection attempts
|
||||
private Predicate<GamePhase> injectionFilter;
|
||||
|
||||
public PlayerInjectionHandler(ClassLoader classLoader, Logger logger, Predicate<GamePhase> injectionFilter,
|
||||
public PlayerInjectionHandler(ClassLoader classLoader, ErrorReporter reporter, Predicate<GamePhase> injectionFilter,
|
||||
ListenerInvoker invoker, Server server) {
|
||||
|
||||
this.classLoader = classLoader;
|
||||
this.logger = logger;
|
||||
this.reporter = reporter;
|
||||
this.invoker = invoker;
|
||||
this.injectionFilter = injectionFilter;
|
||||
this.netLoginInjector = new NetLoginInjector(logger, this, server);
|
||||
this.serverInjection = new InjectedServerConnection(logger, server, netLoginInjector);
|
||||
this.netLoginInjector = new NetLoginInjector(reporter, this, server);
|
||||
this.serverInjection = new InjectedServerConnection(reporter, server, netLoginInjector);
|
||||
serverInjection.injectList();
|
||||
}
|
||||
|
||||
@ -173,11 +172,11 @@ public class PlayerInjectionHandler {
|
||||
// Construct the correct player hook
|
||||
switch (hook) {
|
||||
case NETWORK_HANDLER_FIELDS:
|
||||
return new NetworkFieldInjector(classLoader, logger, player, invoker, sendingFilters);
|
||||
return new NetworkFieldInjector(classLoader, reporter, player, invoker, sendingFilters);
|
||||
case NETWORK_MANAGER_OBJECT:
|
||||
return new NetworkObjectInjector(classLoader, logger, player, invoker, sendingFilters);
|
||||
return new NetworkObjectInjector(classLoader, reporter, player, invoker, sendingFilters);
|
||||
case NETWORK_SERVER_OBJECT:
|
||||
return new NetworkServerInjector(classLoader, logger, player, invoker, sendingFilters, serverInjection);
|
||||
return new NetworkServerInjector(classLoader, reporter, player, invoker, sendingFilters, serverInjection);
|
||||
default:
|
||||
throw new IllegalArgumentException("Cannot construct a player injector.");
|
||||
}
|
||||
@ -198,7 +197,7 @@ public class PlayerInjectionHandler {
|
||||
if (injector != null) {
|
||||
return injector.getPlayer();
|
||||
} else {
|
||||
logger.warning("Unable to find stream: " + inputStream);
|
||||
reporter.reportWarning(this, "Unable to find stream: " + inputStream);
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -310,7 +309,8 @@ public class PlayerInjectionHandler {
|
||||
|
||||
} catch (Exception e) {
|
||||
// Mark this injection attempt as a failure
|
||||
logger.log(Level.SEVERE, "Player hook " + tempHook.toString() + " failed.", e);
|
||||
reporter.reportDetailed(this, "Player hook " + tempHook.toString() + " failed.",
|
||||
e, player, injectionPoint, phase);
|
||||
hookFailed = true;
|
||||
}
|
||||
|
||||
@ -318,7 +318,7 @@ public class PlayerInjectionHandler {
|
||||
tempHook = PlayerInjectHooks.values()[tempHook.ordinal() - 1];
|
||||
|
||||
if (hookFailed)
|
||||
logger.log(Level.INFO, "Switching to " + tempHook.toString() + " instead.");
|
||||
reporter.reportWarning(this, "Switching to " + tempHook.toString() + " instead.");
|
||||
|
||||
// Check for UTTER FAILURE
|
||||
if (tempHook == PlayerInjectHooks.NONE) {
|
||||
@ -353,8 +353,8 @@ public class PlayerInjectionHandler {
|
||||
try {
|
||||
if (injector != null)
|
||||
injector.cleanupAll();
|
||||
} catch (Exception e2) {
|
||||
logger.log(Level.WARNING, "Cleaing up after player hook failed.", e2);
|
||||
} catch (Exception ex) {
|
||||
reporter.reportDetailed(this, "Cleaing up after player hook failed.", ex, injector);
|
||||
}
|
||||
}
|
||||
|
||||
@ -415,7 +415,7 @@ public class PlayerInjectionHandler {
|
||||
|
||||
} catch (IllegalAccessException e) {
|
||||
// Let the user know
|
||||
logger.log(Level.WARNING, "Unable to fully revert old injector. May cause conflicts.", e);
|
||||
reporter.reportWarning(this, "Unable to fully revert old injector. May cause conflicts.", e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -470,7 +470,7 @@ public class PlayerInjectionHandler {
|
||||
if (injector != null)
|
||||
injector.sendServerPacket(packet.getHandle(), filters);
|
||||
else
|
||||
logger.log(Level.WARNING, String.format(
|
||||
reporter.reportWarning(this, String.format(
|
||||
"Unable to send packet %s (%s): Player %s has logged out.",
|
||||
packet.getID(), packet, reciever.getName()
|
||||
));
|
||||
@ -491,7 +491,7 @@ public class PlayerInjectionHandler {
|
||||
if (injector != null)
|
||||
injector.processPacket(mcPacket);
|
||||
else
|
||||
logger.log(Level.WARNING, String.format(
|
||||
reporter.reportWarning(this, String.format(
|
||||
"Unable to receieve packet %s. Player %s has logged out.",
|
||||
mcPacket, player.getName()
|
||||
));
|
||||
@ -537,7 +537,7 @@ public class PlayerInjectionHandler {
|
||||
try {
|
||||
checkListener(listener);
|
||||
} catch (IllegalStateException e) {
|
||||
logger.log(Level.WARNING, "Unsupported listener.", e);
|
||||
reporter.reportWarning(this, "Unsupported listener.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -565,14 +565,6 @@ public class PlayerInjectionHandler {
|
||||
return sendingFilters.toSet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the current logger.
|
||||
* @return Error logger.
|
||||
*/
|
||||
public Logger getLogger() {
|
||||
return logger;
|
||||
}
|
||||
|
||||
public void close() {
|
||||
|
||||
// Guard
|
||||
|
@ -24,8 +24,6 @@ import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketAddress;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import net.minecraft.server.EntityPlayer;
|
||||
import net.minecraft.server.NetLoginHandler;
|
||||
@ -36,6 +34,7 @@ import org.bukkit.craftbukkit.entity.CraftPlayer;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.comphenix.protocol.Packets;
|
||||
import com.comphenix.protocol.error.ErrorReporter;
|
||||
import com.comphenix.protocol.events.PacketContainer;
|
||||
import com.comphenix.protocol.events.PacketEvent;
|
||||
import com.comphenix.protocol.events.PacketListener;
|
||||
@ -100,7 +99,7 @@ abstract class PlayerInjector {
|
||||
protected DataInputStream cachedInput;
|
||||
|
||||
// Handle errors
|
||||
protected Logger logger;
|
||||
protected ErrorReporter reporter;
|
||||
|
||||
// Scheduled action on the next packet event
|
||||
protected Runnable scheduledAction;
|
||||
@ -112,8 +111,8 @@ abstract class PlayerInjector {
|
||||
boolean updateOnLogin;
|
||||
Player updatedPlayer;
|
||||
|
||||
public PlayerInjector(Logger logger, Player player, ListenerInvoker invoker) throws IllegalAccessException {
|
||||
this.logger = logger;
|
||||
public PlayerInjector(ErrorReporter reporter, Player player, ListenerInvoker invoker) throws IllegalAccessException {
|
||||
this.reporter = reporter;
|
||||
this.player = player;
|
||||
this.invoker = invoker;
|
||||
}
|
||||
@ -303,19 +302,24 @@ abstract class PlayerInjector {
|
||||
disconnect.invoke(handler, message);
|
||||
return;
|
||||
} catch (IllegalArgumentException e) {
|
||||
logger.log(Level.WARNING, "Invalid argument passed to disconnect method: " + message, e);
|
||||
reporter.reportDetailed(this, "Invalid argument passed to disconnect method: " + message, e, handler);
|
||||
} catch (IllegalAccessException e) {
|
||||
logger.log(Level.SEVERE, "Unable to access disconnect method.", e);
|
||||
reporter.reportWarning(this, "Unable to access disconnect method.", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Fuck it
|
||||
try {
|
||||
getSocket().close();
|
||||
} catch (IOException e) {
|
||||
logger.log(Level.SEVERE, "Unable to close socket.", e);
|
||||
Socket socket = getSocket();
|
||||
|
||||
try {
|
||||
socket.close();
|
||||
} catch (IOException e) {
|
||||
reporter.reportDetailed(this, "Unable to close socket.", e, socket);
|
||||
}
|
||||
|
||||
} catch (IllegalAccessException e) {
|
||||
logger.log(Level.SEVERE, "Insufficient permissions. Cannot close socket.", e);
|
||||
reporter.reportWarning(this, "Insufficient permissions. Cannot close socket.", e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -332,7 +336,7 @@ abstract class PlayerInjector {
|
||||
return null;
|
||||
|
||||
hasProxyType = true;
|
||||
logger.log(Level.WARNING, "Detected server handler proxy type by another plugin. Conflict may occur!");
|
||||
reporter.reportWarning(this, "Detected server handler proxy type by another plugin. Conflict may occur!");
|
||||
|
||||
// No? Is it a Proxy type?
|
||||
try {
|
||||
@ -347,7 +351,7 @@ abstract class PlayerInjector {
|
||||
}
|
||||
|
||||
} catch (IllegalAccessException e) {
|
||||
logger.warning("Unable to load server handler from proxy type.");
|
||||
reporter.reportWarning(this, "Unable to load server handler from proxy type.");
|
||||
}
|
||||
|
||||
// Nope, just go with it
|
||||
@ -511,7 +515,7 @@ abstract class PlayerInjector {
|
||||
try {
|
||||
updatedPlayer = getEntityPlayer(getNetHandler()).getBukkitEntity();
|
||||
} catch (IllegalAccessException e) {
|
||||
logger.log(Level.WARNING, "Cannot update player in PlayerEvent.", e);
|
||||
reporter.reportDetailed(this, "Cannot update player in PlayerEvent.", e, packet);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user