Archiviert
13
0

Wait 5 seconds before unhooking every player in the server.

Dieser Commit ist enthalten in:
Kristian S. Stangeland 2012-10-17 00:46:51 +02:00
Ursprung 476a918794
Commit 4cd5d04cae
3 geänderte Dateien mit 174 neuen und 11 gelöschten Zeilen

Datei anzeigen

@ -29,6 +29,7 @@ import com.comphenix.protocol.async.AsyncFilterManager;
import com.comphenix.protocol.events.ConnectionSide;
import com.comphenix.protocol.events.MonitorAdapter;
import com.comphenix.protocol.events.PacketEvent;
import com.comphenix.protocol.injector.DelayedSingleTask;
import com.comphenix.protocol.injector.PacketFilterManager;
import com.comphenix.protocol.metrics.Statistics;
import com.comphenix.protocol.reflect.compiler.BackgroundCompiler;
@ -58,13 +59,17 @@ public class ProtocolLibrary extends JavaPlugin {
private int tickCounter = 0;
private static final int ASYNC_PACKET_DELAY = 1;
// Used to unhook players after a delay
private DelayedSingleTask unhookTask;
// Used for debugging
private boolean debugListener;
@Override
public void onLoad() {
logger = getLoggerSafely();
protocolManager = new PacketFilterManager(getClassLoader(), getServer(), logger);
unhookTask = new DelayedSingleTask(this);
protocolManager = new PacketFilterManager(getClassLoader(), getServer(), unhookTask, logger);
}
@Override
@ -181,6 +186,7 @@ public class ProtocolLibrary extends JavaPlugin {
asyncPacketTask = -1;
}
unhookTask.close();
protocolManager.close();
protocolManager = null;
statistisc = null;

Datei anzeigen

@ -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();
}
}

Datei anzeigen

@ -90,6 +90,13 @@ public final class PacketFilterManager implements ProtocolManager, ListenerInvok
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
private Set<PacketListener> packetListeners =
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.
* @param unhookTask
*/
public PacketFilterManager(ClassLoader classLoader, Server server, Logger logger) {
public PacketFilterManager(ClassLoader classLoader, Server server, DelayedSingleTask unhookTask, Logger logger) {
if (logger == null)
throw new IllegalArgumentException("logger cannot be NULL.");
if (classLoader == 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
Predicate<GamePhase> isInjectionNecessary = new Predicate<GamePhase>() {
@Override
@ -144,17 +161,15 @@ public final class PacketFilterManager implements ProtocolManager, ListenerInvok
if (phase.hasLogin())
result &= getPhaseLoginCount() > 0;
// Note that we will still hook players if the unhooking has been delayed
if (phase.hasPlaying())
result &= getPhasePlayingCount() > 0;
result &= getPhasePlayingCount() > 0 || finalUnhookTask.isRunning();
return result;
}
};
try {
// Initialize values
this.server = server;
this.classLoader = classLoader;
this.logger = logger;
// Initialize injection mangers
this.playerInjection = new PlayerInjectionHandler(classLoader, logger, isInjectionNecessary, this, server);
this.packetInjector = new PacketInjector(classLoader, this, playerInjection);
this.asyncFilterManager = new AsyncFilterManager(logger, server.getScheduler(), this);
@ -257,6 +272,10 @@ public final class PacketFilterManager implements ProtocolManager, ListenerInvok
// We may have to inject into every current player
if (phase.hasPlaying()) {
if (phasePlayingCount.incrementAndGet() == 1) {
// If we're about to uninitialize every player, cancel that instead
if (unhookTask.isRunning())
unhookTask.cancel();
else
// Inject our hook into already existing players
initializePlayers(server.getOnlinePlayers());
}
@ -274,9 +293,15 @@ public final class PacketFilterManager implements ProtocolManager, ListenerInvok
// We may have to inject into every current player
if (phase.hasPlaying()) {
if (phasePlayingCount.decrementAndGet() == 0) {
// Schedule unhooking in the future
unhookTask.schedule(UNHOOK_DELAY, new Runnable() {
@Override
public void run() {
// Inject our hook into already existing players
uninitializePlayers(server.getOnlinePlayers());
}
});
}
}
}