Wait 5 seconds before unhooking every player in the server.
Dieser Commit ist enthalten in:
Ursprung
476a918794
Commit
4cd5d04cae
@ -29,6 +29,7 @@ import com.comphenix.protocol.async.AsyncFilterManager;
|
|||||||
import com.comphenix.protocol.events.ConnectionSide;
|
import com.comphenix.protocol.events.ConnectionSide;
|
||||||
import com.comphenix.protocol.events.MonitorAdapter;
|
import com.comphenix.protocol.events.MonitorAdapter;
|
||||||
import com.comphenix.protocol.events.PacketEvent;
|
import com.comphenix.protocol.events.PacketEvent;
|
||||||
|
import com.comphenix.protocol.injector.DelayedSingleTask;
|
||||||
import com.comphenix.protocol.injector.PacketFilterManager;
|
import com.comphenix.protocol.injector.PacketFilterManager;
|
||||||
import com.comphenix.protocol.metrics.Statistics;
|
import com.comphenix.protocol.metrics.Statistics;
|
||||||
import com.comphenix.protocol.reflect.compiler.BackgroundCompiler;
|
import com.comphenix.protocol.reflect.compiler.BackgroundCompiler;
|
||||||
@ -58,13 +59,17 @@ public class ProtocolLibrary extends JavaPlugin {
|
|||||||
private int tickCounter = 0;
|
private int tickCounter = 0;
|
||||||
private static final int ASYNC_PACKET_DELAY = 1;
|
private static final int ASYNC_PACKET_DELAY = 1;
|
||||||
|
|
||||||
|
// Used to unhook players after a delay
|
||||||
|
private DelayedSingleTask unhookTask;
|
||||||
|
|
||||||
// Used for debugging
|
// Used for debugging
|
||||||
private boolean debugListener;
|
private boolean debugListener;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLoad() {
|
public void onLoad() {
|
||||||
logger = getLoggerSafely();
|
logger = getLoggerSafely();
|
||||||
protocolManager = new PacketFilterManager(getClassLoader(), getServer(), logger);
|
unhookTask = new DelayedSingleTask(this);
|
||||||
|
protocolManager = new PacketFilterManager(getClassLoader(), getServer(), unhookTask, logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -181,6 +186,7 @@ public class ProtocolLibrary extends JavaPlugin {
|
|||||||
asyncPacketTask = -1;
|
asyncPacketTask = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unhookTask.close();
|
||||||
protocolManager.close();
|
protocolManager.close();
|
||||||
protocolManager = null;
|
protocolManager = null;
|
||||||
statistisc = null;
|
statistisc = null;
|
||||||
|
@ -0,0 +1,132 @@
|
|||||||
|
package com.comphenix.protocol.injector;
|
||||||
|
|
||||||
|
import org.bukkit.plugin.Plugin;
|
||||||
|
import org.bukkit.scheduler.BukkitScheduler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a single delayed task.
|
||||||
|
*
|
||||||
|
* @author Kristian
|
||||||
|
*/
|
||||||
|
public class DelayedSingleTask {
|
||||||
|
|
||||||
|
protected int taskID = -1;
|
||||||
|
protected Plugin plugin;
|
||||||
|
protected BukkitScheduler scheduler;
|
||||||
|
protected boolean closed;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a single task scheduler.
|
||||||
|
* @param plugin - owner plugin.
|
||||||
|
*/
|
||||||
|
public DelayedSingleTask(Plugin plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
this.scheduler = plugin.getServer().getScheduler();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a single task scheduler.
|
||||||
|
* @param plugin - owner plugin.
|
||||||
|
* @param scheduler - specialized scheduler.
|
||||||
|
*/
|
||||||
|
public DelayedSingleTask(Plugin plugin, BukkitScheduler scheduler) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
this.scheduler = scheduler;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedule a single task for execution.
|
||||||
|
* <p>
|
||||||
|
* Any previously scheduled task will be automatically cancelled.
|
||||||
|
* <p>
|
||||||
|
* Note that a tick delay of zero will execute the task immediately.
|
||||||
|
*
|
||||||
|
* @param ticksDelay - number of ticks before the task is executed.
|
||||||
|
* @param task - the task to schedule.
|
||||||
|
* @return TRUE if the task was successfully scheduled or executed, FALSE otherwise.
|
||||||
|
*/
|
||||||
|
public boolean schedule(long ticksDelay, Runnable task) {
|
||||||
|
if (ticksDelay < 0)
|
||||||
|
throw new IllegalArgumentException("Tick delay cannot be negative.");
|
||||||
|
if (task == null)
|
||||||
|
throw new IllegalArgumentException("task cannot be NULL");
|
||||||
|
if (closed)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Special case
|
||||||
|
if (ticksDelay == 0) {
|
||||||
|
task.run();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Boilerplate, boilerplate
|
||||||
|
final Runnable dispatch = task;
|
||||||
|
|
||||||
|
// Don't run multiple tasks!
|
||||||
|
cancel();
|
||||||
|
taskID = scheduler.scheduleSyncDelayedTask(plugin, new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
dispatch.run();
|
||||||
|
taskID = -1;
|
||||||
|
}
|
||||||
|
}, ticksDelay);
|
||||||
|
|
||||||
|
return isRunning();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not a future task is scheduled to be executed.
|
||||||
|
* @return TRUE if a current task has been scheduled for execution, FALSE otherwise.
|
||||||
|
*/
|
||||||
|
public boolean isRunning() {
|
||||||
|
return taskID >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cancel a future task from being executed.
|
||||||
|
* @return TRUE if a task was cancelled, FALSE otherwise.
|
||||||
|
*/
|
||||||
|
public boolean cancel() {
|
||||||
|
if (isRunning()) {
|
||||||
|
scheduler.cancelTask(taskID);
|
||||||
|
taskID = -1;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the raw task ID.
|
||||||
|
* @return Raw task ID, or negative one if no task has been scheduled.
|
||||||
|
*/
|
||||||
|
public int getTaskID() {
|
||||||
|
return taskID;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the plugin this task belongs to.
|
||||||
|
* @return The plugin scheduling the current taks.
|
||||||
|
*/
|
||||||
|
public Plugin getPlugin() {
|
||||||
|
return plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop the current task and all future tasks scheduled by this instance.
|
||||||
|
*/
|
||||||
|
public synchronized void close() {
|
||||||
|
if (!closed) {
|
||||||
|
cancel();
|
||||||
|
plugin = null;
|
||||||
|
scheduler = null;
|
||||||
|
closed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void finalize() throws Throwable {
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
}
|
@ -90,6 +90,13 @@ public final class PacketFilterManager implements ProtocolManager, ListenerInvok
|
|||||||
NETWORK_SERVER_OBJECT;
|
NETWORK_SERVER_OBJECT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The amount of time to wait until we actually unhook every player
|
||||||
|
private static final int TICKS_PER_SECOND = 20;
|
||||||
|
private static final int UNHOOK_DELAY = 5 * TICKS_PER_SECOND;
|
||||||
|
|
||||||
|
// Delayed unhook
|
||||||
|
private DelayedSingleTask unhookTask;
|
||||||
|
|
||||||
// Create a concurrent set
|
// Create a concurrent set
|
||||||
private Set<PacketListener> packetListeners =
|
private Set<PacketListener> packetListeners =
|
||||||
Collections.newSetFromMap(new ConcurrentHashMap<PacketListener, Boolean>());
|
Collections.newSetFromMap(new ConcurrentHashMap<PacketListener, Boolean>());
|
||||||
@ -129,13 +136,23 @@ public final class PacketFilterManager implements ProtocolManager, ListenerInvok
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Only create instances of this class if protocol lib is disabled.
|
* Only create instances of this class if protocol lib is disabled.
|
||||||
|
* @param unhookTask
|
||||||
*/
|
*/
|
||||||
public PacketFilterManager(ClassLoader classLoader, Server server, Logger logger) {
|
public PacketFilterManager(ClassLoader classLoader, Server server, DelayedSingleTask unhookTask, Logger logger) {
|
||||||
if (logger == null)
|
if (logger == null)
|
||||||
throw new IllegalArgumentException("logger cannot be NULL.");
|
throw new IllegalArgumentException("logger cannot be NULL.");
|
||||||
if (classLoader == null)
|
if (classLoader == null)
|
||||||
throw new IllegalArgumentException("classLoader cannot be NULL.");
|
throw new IllegalArgumentException("classLoader cannot be NULL.");
|
||||||
|
|
||||||
|
// Just boilerplate
|
||||||
|
final DelayedSingleTask finalUnhookTask = unhookTask;
|
||||||
|
|
||||||
|
// References
|
||||||
|
this.unhookTask = unhookTask;
|
||||||
|
this.server = server;
|
||||||
|
this.classLoader = classLoader;
|
||||||
|
this.logger = logger;
|
||||||
|
|
||||||
// Used to determine if injection is needed
|
// Used to determine if injection is needed
|
||||||
Predicate<GamePhase> isInjectionNecessary = new Predicate<GamePhase>() {
|
Predicate<GamePhase> isInjectionNecessary = new Predicate<GamePhase>() {
|
||||||
@Override
|
@Override
|
||||||
@ -144,17 +161,15 @@ public final class PacketFilterManager implements ProtocolManager, ListenerInvok
|
|||||||
|
|
||||||
if (phase.hasLogin())
|
if (phase.hasLogin())
|
||||||
result &= getPhaseLoginCount() > 0;
|
result &= getPhaseLoginCount() > 0;
|
||||||
|
// Note that we will still hook players if the unhooking has been delayed
|
||||||
if (phase.hasPlaying())
|
if (phase.hasPlaying())
|
||||||
result &= getPhasePlayingCount() > 0;
|
result &= getPhasePlayingCount() > 0 || finalUnhookTask.isRunning();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Initialize values
|
// Initialize injection mangers
|
||||||
this.server = server;
|
|
||||||
this.classLoader = classLoader;
|
|
||||||
this.logger = logger;
|
|
||||||
this.playerInjection = new PlayerInjectionHandler(classLoader, logger, isInjectionNecessary, this, server);
|
this.playerInjection = new PlayerInjectionHandler(classLoader, logger, isInjectionNecessary, this, server);
|
||||||
this.packetInjector = new PacketInjector(classLoader, this, playerInjection);
|
this.packetInjector = new PacketInjector(classLoader, this, playerInjection);
|
||||||
this.asyncFilterManager = new AsyncFilterManager(logger, server.getScheduler(), this);
|
this.asyncFilterManager = new AsyncFilterManager(logger, server.getScheduler(), this);
|
||||||
@ -257,8 +272,12 @@ public final class PacketFilterManager implements ProtocolManager, ListenerInvok
|
|||||||
// We may have to inject into every current player
|
// We may have to inject into every current player
|
||||||
if (phase.hasPlaying()) {
|
if (phase.hasPlaying()) {
|
||||||
if (phasePlayingCount.incrementAndGet() == 1) {
|
if (phasePlayingCount.incrementAndGet() == 1) {
|
||||||
// Inject our hook into already existing players
|
// If we're about to uninitialize every player, cancel that instead
|
||||||
initializePlayers(server.getOnlinePlayers());
|
if (unhookTask.isRunning())
|
||||||
|
unhookTask.cancel();
|
||||||
|
else
|
||||||
|
// Inject our hook into already existing players
|
||||||
|
initializePlayers(server.getOnlinePlayers());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -274,8 +293,14 @@ public final class PacketFilterManager implements ProtocolManager, ListenerInvok
|
|||||||
// We may have to inject into every current player
|
// We may have to inject into every current player
|
||||||
if (phase.hasPlaying()) {
|
if (phase.hasPlaying()) {
|
||||||
if (phasePlayingCount.decrementAndGet() == 0) {
|
if (phasePlayingCount.decrementAndGet() == 0) {
|
||||||
// Inject our hook into already existing players
|
// Schedule unhooking in the future
|
||||||
uninitializePlayers(server.getOnlinePlayers());
|
unhookTask.schedule(UNHOOK_DELAY, new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
// Inject our hook into already existing players
|
||||||
|
uninitializePlayers(server.getOnlinePlayers());
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
In neuem Issue referenzieren
Einen Benutzer sperren