// Intercept all write methods
channelField.setValue(new ChannelProxy(originalChannel, MinecraftReflection.getPacketClass()) {
@Override
protected <T> Callable<T> onMessageScheduled(final Callable<T> callable, FieldAccessor packetAccessor) {
final PacketEvent event = handleScheduled(callable, packetAccessor);
// Handle cancelled events
if (event != null && event.isCancelled())
return null;
return new Callable<T>() {
@Override
public T call() throws Exception {
T result = null;
// This field must only be updated in the pipeline thread
currentEvent = event;
result = callable.call();
currentEvent = null;
return result;
}
};
}
@Override
protected Runnable onMessageScheduled(final Runnable runnable, FieldAccessor packetAccessor) {
final PacketEvent event = handleScheduled(runnable, packetAccessor);
// Handle cancelled events
if (event != null && event.isCancelled())
return null;
return new Runnable() {
@Override
public void run() {
currentEvent = event;
runnable.run();
currentEvent = null;
}
};
}
protected PacketEvent handleScheduled(Object instance, FieldAccessor accessor) {
// Let the filters handle this packet
Object original = accessor.get(instance);
// See if we've been instructed not to process packets
if (!scheduleProcessPackets.get()) {
NetworkMarker marker = getMarker(original);
if (marker != null) {
PacketEvent result = new PacketEvent(ChannelInjector.class);
result.setNetworkMarker(marker);
return result;
} else {
return BYPASSED_PACKET;
}
}
PacketEvent event = processSending(original);
if (event != null && !event.isCancelled()) {
Object changed = event.getPacket().getHandle();
// Change packet to be scheduled
if (original != changed)
accessor.set(instance, changed);
};