mirror of
https://github.com/dmulloy2/ProtocolLib.git
synced 2025-02-11 10:01:56 +01:00
Fix index out of bounds exception
Also make /all/ the IntelliJ code changes Fixes #469
This commit is contained in:
parent
015099b92e
commit
fb2d5016e5
@ -16,24 +16,14 @@
|
|||||||
*/
|
*/
|
||||||
package com.comphenix.protocol.injector.netty;
|
package com.comphenix.protocol.injector.netty;
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
import java.net.SocketAddress;
|
import java.net.SocketAddress;
|
||||||
import java.util.ArrayDeque;
|
import java.util.*;
|
||||||
import java.util.Deque;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.ListIterator;
|
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.NoSuchElementException;
|
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
import net.sf.cglib.proxy.Factory;
|
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
|
|
||||||
import com.comphenix.protocol.PacketType;
|
import com.comphenix.protocol.PacketType;
|
||||||
import com.comphenix.protocol.PacketType.Protocol;
|
import com.comphenix.protocol.PacketType.Protocol;
|
||||||
import com.comphenix.protocol.ProtocolLibrary;
|
import com.comphenix.protocol.ProtocolLibrary;
|
||||||
@ -58,12 +48,7 @@ import com.google.common.base.Preconditions;
|
|||||||
import com.google.common.collect.MapMaker;
|
import com.google.common.collect.MapMaker;
|
||||||
|
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.channel.Channel;
|
import io.netty.channel.*;
|
||||||
import io.netty.channel.ChannelHandler;
|
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
|
||||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
|
||||||
import io.netty.channel.ChannelPipeline;
|
|
||||||
import io.netty.channel.ChannelPromise;
|
|
||||||
import io.netty.channel.socket.SocketChannel;
|
import io.netty.channel.socket.SocketChannel;
|
||||||
import io.netty.handler.codec.ByteToMessageDecoder;
|
import io.netty.handler.codec.ByteToMessageDecoder;
|
||||||
import io.netty.handler.codec.MessageToByteEncoder;
|
import io.netty.handler.codec.MessageToByteEncoder;
|
||||||
@ -71,16 +56,20 @@ import io.netty.util.AttributeKey;
|
|||||||
import io.netty.util.concurrent.GenericFutureListener;
|
import io.netty.util.concurrent.GenericFutureListener;
|
||||||
import io.netty.util.internal.TypeParameterMatcher;
|
import io.netty.util.internal.TypeParameterMatcher;
|
||||||
|
|
||||||
|
import net.sf.cglib.proxy.Factory;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a channel injector.
|
* Represents a channel injector.
|
||||||
* @author Kristian
|
* @author Kristian
|
||||||
*/
|
*/
|
||||||
public class ChannelInjector extends ByteToMessageDecoder implements Injector {
|
public class ChannelInjector extends ByteToMessageDecoder implements Injector {
|
||||||
public static final ReportType REPORT_CANNOT_INTERCEPT_SERVER_PACKET = new ReportType("Unable to intercept a written server packet.");
|
private static final ReportType REPORT_CANNOT_INTERCEPT_SERVER_PACKET = new ReportType("Unable to intercept a written server packet.");
|
||||||
public static final ReportType REPORT_CANNOT_INTERCEPT_CLIENT_PACKET = new ReportType("Unable to intercept a read client packet.");
|
private static final ReportType REPORT_CANNOT_INTERCEPT_CLIENT_PACKET = new ReportType("Unable to intercept a read client packet.");
|
||||||
public static final ReportType REPORT_CANNOT_EXECUTE_IN_CHANNEL_THREAD = new ReportType("Cannot execute code in channel thread.");
|
private static final ReportType REPORT_CANNOT_EXECUTE_IN_CHANNEL_THREAD = new ReportType("Cannot execute code in channel thread.");
|
||||||
public static final ReportType REPORT_CANNOT_FIND_GET_VERSION = new ReportType("Cannot find getVersion() in NetworkMananger");
|
private static final ReportType REPORT_CANNOT_SEND_PACKET = new ReportType("Unable to send packet %s to %s");
|
||||||
public static final ReportType REPORT_CANNOT_SEND_PACKET = new ReportType("Unable to send packet %s to %s");
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates that a packet has bypassed packet listeners.
|
* Indicates that a packet has bypassed packet listeners.
|
||||||
@ -98,12 +87,7 @@ public class ChannelInjector extends ByteToMessageDecoder implements Injector {
|
|||||||
private static AttributeKey<Integer> PROTOCOL_KEY;
|
private static AttributeKey<Integer> PROTOCOL_KEY;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
// Shout-outs to reloading
|
PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL-" + keyId.getAndIncrement());
|
||||||
try {
|
|
||||||
PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL");
|
|
||||||
} catch (IllegalArgumentException ex) {
|
|
||||||
PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL-" + keyId.getAndIncrement());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Saved accessors
|
// Saved accessors
|
||||||
@ -148,18 +132,13 @@ public class ChannelInjector extends ByteToMessageDecoder implements Injector {
|
|||||||
/**
|
/**
|
||||||
* A flag set by the main thread to indiciate that a packet should not be processed.
|
* A flag set by the main thread to indiciate that a packet should not be processed.
|
||||||
*/
|
*/
|
||||||
private final ThreadLocal<Boolean> scheduleProcessPackets = new ThreadLocal<Boolean>() {
|
private final ThreadLocal<Boolean> scheduleProcessPackets = ThreadLocal.withInitial(() -> true);
|
||||||
@Override
|
|
||||||
protected Boolean initialValue() {
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
// Other handlers
|
// Other handlers
|
||||||
private ByteToMessageDecoder vanillaDecoder;
|
private ByteToMessageDecoder vanillaDecoder;
|
||||||
private MessageToByteEncoder<Object> vanillaEncoder;
|
private MessageToByteEncoder<Object> vanillaEncoder;
|
||||||
|
|
||||||
private Deque<PacketEvent> finishQueue = new ArrayDeque<PacketEvent>();
|
private Deque<PacketEvent> finishQueue = new ArrayDeque<>();
|
||||||
|
|
||||||
// The channel listener
|
// The channel listener
|
||||||
private ChannelListener channelListener;
|
private ChannelListener channelListener;
|
||||||
@ -179,7 +158,7 @@ public class ChannelInjector extends ByteToMessageDecoder implements Injector {
|
|||||||
* @param channelListener - a listener.
|
* @param channelListener - a listener.
|
||||||
* @param factory - the factory that created this injector
|
* @param factory - the factory that created this injector
|
||||||
*/
|
*/
|
||||||
public ChannelInjector(Player player, Object networkManager, Channel channel, ChannelListener channelListener, InjectionFactory factory) {
|
ChannelInjector(Player player, Object networkManager, Channel channel, ChannelListener channelListener, InjectionFactory factory) {
|
||||||
this.player = Preconditions.checkNotNull(player, "player cannot be NULL");
|
this.player = Preconditions.checkNotNull(player, "player cannot be NULL");
|
||||||
this.networkManager = Preconditions.checkNotNull(networkManager, "networkMananger cannot be NULL");
|
this.networkManager = Preconditions.checkNotNull(networkManager, "networkMananger cannot be NULL");
|
||||||
this.originalChannel = Preconditions.checkNotNull(channel, "channel cannot be NULL");
|
this.originalChannel = Preconditions.checkNotNull(channel, "channel cannot be NULL");
|
||||||
@ -188,8 +167,9 @@ public class ChannelInjector extends ByteToMessageDecoder implements Injector {
|
|||||||
this.processor = new NetworkProcessor(ProtocolLibrary.getErrorReporter());
|
this.processor = new NetworkProcessor(ProtocolLibrary.getErrorReporter());
|
||||||
|
|
||||||
// Get the channel field
|
// Get the channel field
|
||||||
this.channelField = new VolatileField(FuzzyReflection.fromObject(networkManager, true).getFieldByType("channel", Channel.class),
|
this.channelField = new VolatileField(FuzzyReflection
|
||||||
networkManager, true);
|
.fromObject(networkManager, true)
|
||||||
|
.getFieldByType("channel", Channel.class), networkManager, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -217,12 +197,7 @@ public class ChannelInjector extends ByteToMessageDecoder implements Injector {
|
|||||||
// pipeline with only some of the handlers removed
|
// pipeline with only some of the handlers removed
|
||||||
if (Bukkit.isPrimaryThread()) {
|
if (Bukkit.isPrimaryThread()) {
|
||||||
// Just like in the close() method, we'll avoid blocking the main thread
|
// Just like in the close() method, we'll avoid blocking the main thread
|
||||||
executeInChannelThread(new Runnable() {
|
executeInChannelThread(this::inject);
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
inject();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return false; // We don't know
|
return false; // We don't know
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -236,9 +211,9 @@ public class ChannelInjector extends ByteToMessageDecoder implements Injector {
|
|||||||
vanillaEncoder = (MessageToByteEncoder<Object>) originalChannel.pipeline().get("encoder");
|
vanillaEncoder = (MessageToByteEncoder<Object>) originalChannel.pipeline().get("encoder");
|
||||||
|
|
||||||
if (vanillaDecoder == null)
|
if (vanillaDecoder == null)
|
||||||
throw new IllegalArgumentException("Unable to find vanilla decoder in " + originalChannel.pipeline() );
|
throw new IllegalArgumentException("Unable to find vanilla decoder in " + originalChannel.pipeline());
|
||||||
if (vanillaEncoder == null)
|
if (vanillaEncoder == null)
|
||||||
throw new IllegalArgumentException("Unable to find vanilla encoder in " + originalChannel.pipeline() );
|
throw new IllegalArgumentException("Unable to find vanilla encoder in " + originalChannel.pipeline());
|
||||||
patchEncoder(vanillaEncoder);
|
patchEncoder(vanillaEncoder);
|
||||||
|
|
||||||
if (DECODE_BUFFER == null)
|
if (DECODE_BUFFER == null)
|
||||||
@ -251,7 +226,7 @@ public class ChannelInjector extends ByteToMessageDecoder implements Injector {
|
|||||||
// Intercept sent packets
|
// Intercept sent packets
|
||||||
MessageToByteEncoder<Object> protocolEncoder = new MessageToByteEncoder<Object>() {
|
MessageToByteEncoder<Object> protocolEncoder = new MessageToByteEncoder<Object>() {
|
||||||
@Override
|
@Override
|
||||||
protected void encode(ChannelHandlerContext ctx, Object packet, ByteBuf output) throws Exception {
|
protected void encode(ChannelHandlerContext ctx, Object packet, ByteBuf output) {
|
||||||
if (packet instanceof WirePacket) {
|
if (packet instanceof WirePacket) {
|
||||||
// Special case for wire format
|
// Special case for wire format
|
||||||
ChannelInjector.this.encodeWirePacket((WirePacket) packet, output);
|
ChannelInjector.this.encodeWirePacket((WirePacket) packet, output);
|
||||||
@ -263,17 +238,17 @@ public class ChannelInjector extends ByteToMessageDecoder implements Injector {
|
|||||||
@Override
|
@Override
|
||||||
public void write(ChannelHandlerContext ctx, Object packet, ChannelPromise promise) throws Exception {
|
public void write(ChannelHandlerContext ctx, Object packet, ChannelPromise promise) throws Exception {
|
||||||
super.write(ctx, packet, promise);
|
super.write(ctx, packet, promise);
|
||||||
ChannelInjector.this.finalWrite(ctx, packet, promise);
|
ChannelInjector.this.finalWrite();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Intercept recieved packets
|
// Intercept recieved packets
|
||||||
ChannelInboundHandlerAdapter finishHandler = new ChannelInboundHandlerAdapter() {
|
ChannelInboundHandlerAdapter finishHandler = new ChannelInboundHandlerAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
|
public void channelRead(ChannelHandlerContext ctx, Object msg) {
|
||||||
// Execute context first
|
// Execute context first
|
||||||
ctx.fireChannelRead(msg);
|
ctx.fireChannelRead(msg);
|
||||||
ChannelInjector.this.finishRead(ctx, msg);
|
ChannelInjector.this.finishRead();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -313,17 +288,14 @@ public class ChannelInjector extends ByteToMessageDecoder implements Injector {
|
|||||||
if (event != null && event.isCancelled())
|
if (event != null && event.isCancelled())
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return new Callable<T>() {
|
return () -> {
|
||||||
@Override
|
T result;
|
||||||
public T call() throws Exception {
|
|
||||||
T result = null;
|
|
||||||
|
|
||||||
// This field must only be updated in the pipeline thread
|
// This field must only be updated in the pipeline thread
|
||||||
currentEvent = event;
|
currentEvent = event;
|
||||||
result = callable.call();
|
result = callable.call();
|
||||||
currentEvent = null;
|
currentEvent = null;
|
||||||
return result;
|
return result;
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -335,17 +307,14 @@ public class ChannelInjector extends ByteToMessageDecoder implements Injector {
|
|||||||
if (event != null && event.isCancelled())
|
if (event != null && event.isCancelled())
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return new Runnable() {
|
return () -> {
|
||||||
@Override
|
currentEvent = event;
|
||||||
public void run() {
|
runnable.run();
|
||||||
currentEvent = event;
|
currentEvent = null;
|
||||||
runnable.run();
|
|
||||||
currentEvent = null;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
protected PacketEvent handleScheduled(Object instance, FieldAccessor accessor) {
|
PacketEvent handleScheduled(Object instance, FieldAccessor accessor) {
|
||||||
// Let the filters handle this packet
|
// Let the filters handle this packet
|
||||||
Object original = accessor.get(instance);
|
Object original = accessor.get(instance);
|
||||||
|
|
||||||
@ -361,15 +330,17 @@ public class ChannelInjector extends ByteToMessageDecoder implements Injector {
|
|||||||
return BYPASSED_PACKET;
|
return BYPASSED_PACKET;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PacketEvent event = processSending(original);
|
|
||||||
|
|
||||||
|
PacketEvent event = processSending(original);
|
||||||
if (event != null && !event.isCancelled()) {
|
if (event != null && !event.isCancelled()) {
|
||||||
Object changed = event.getPacket().getHandle();
|
Object changed = event.getPacket().getHandle();
|
||||||
|
|
||||||
// Change packet to be scheduled
|
// Change packet to be scheduled
|
||||||
if (original != changed)
|
if (original != changed) {
|
||||||
accessor.set(instance, changed);
|
accessor.set(instance, changed);
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return event != null ? event : BYPASSED_PACKET;
|
return event != null ? event : BYPASSED_PACKET;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -406,17 +377,20 @@ public class ChannelInjector extends ByteToMessageDecoder implements Injector {
|
|||||||
if (ENCODER_TYPE_MATCHER == null) {
|
if (ENCODER_TYPE_MATCHER == null) {
|
||||||
ENCODER_TYPE_MATCHER = Accessors.getFieldAccessor(encoder.getClass(), "matcher", true);
|
ENCODER_TYPE_MATCHER = Accessors.getFieldAccessor(encoder.getClass(), "matcher", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
ENCODER_TYPE_MATCHER.set(encoder, TypeParameterMatcher.get(MinecraftReflection.getPacketClass()));
|
ENCODER_TYPE_MATCHER.set(encoder, TypeParameterMatcher.get(MinecraftReflection.getPacketClass()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
|
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
|
||||||
if (channelListener.isDebug())
|
if (channelListener.isDebug()) {
|
||||||
cause.printStackTrace();
|
cause.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
super.exceptionCaught(ctx, cause);
|
super.exceptionCaught(ctx, cause);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void encodeWirePacket(WirePacket packet, ByteBuf output) throws Exception {
|
private void encodeWirePacket(WirePacket packet, ByteBuf output) {
|
||||||
packet.writeId(output);
|
packet.writeId(output);
|
||||||
packet.writeBytes(output);
|
packet.writeBytes(output);
|
||||||
}
|
}
|
||||||
@ -426,9 +400,8 @@ public class ChannelInjector extends ByteToMessageDecoder implements Injector {
|
|||||||
* @param ctx - the current context.
|
* @param ctx - the current context.
|
||||||
* @param packet - the packet to encode to a byte array.
|
* @param packet - the packet to encode to a byte array.
|
||||||
* @param output - the output byte array.
|
* @param output - the output byte array.
|
||||||
* @throws Exception If anything went wrong.
|
|
||||||
*/
|
*/
|
||||||
protected void encode(ChannelHandlerContext ctx, Object packet, ByteBuf output) throws Exception {
|
private void encode(ChannelHandlerContext ctx, Object packet, ByteBuf output) {
|
||||||
NetworkMarker marker = null;
|
NetworkMarker marker = null;
|
||||||
PacketEvent event = currentEvent;
|
PacketEvent event = currentEvent;
|
||||||
|
|
||||||
@ -457,6 +430,7 @@ public class ChannelInjector extends ByteToMessageDecoder implements Injector {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event != null) {
|
if (event != null) {
|
||||||
// Retrieve marker without accidentally constructing it
|
// Retrieve marker without accidentally constructing it
|
||||||
marker = NetworkMarker.getNetworkMarker(event);
|
marker = NetworkMarker.getNetworkMarker(event);
|
||||||
@ -476,7 +450,6 @@ public class ChannelInjector extends ByteToMessageDecoder implements Injector {
|
|||||||
|
|
||||||
// Sent listeners?
|
// Sent listeners?
|
||||||
finalEvent = event;
|
finalEvent = event;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
channelListener.getReporter().reportDetailed(this,
|
channelListener.getReporter().reportDetailed(this,
|
||||||
@ -491,12 +464,9 @@ public class ChannelInjector extends ByteToMessageDecoder implements Injector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invoked when a packet has been written to the channel.
|
* Invoked when a packet has been written to the channel
|
||||||
* @param ctx - current context.
|
|
||||||
* @param packet - the packet that has been written.
|
|
||||||
* @param promise - a promise.
|
|
||||||
*/
|
*/
|
||||||
protected void finalWrite(ChannelHandlerContext ctx, Object packet, ChannelPromise promise) {
|
private void finalWrite() {
|
||||||
PacketEvent event = finalEvent;
|
PacketEvent event = finalEvent;
|
||||||
|
|
||||||
if (event != null) {
|
if (event != null) {
|
||||||
@ -510,17 +480,11 @@ public class ChannelInjector extends ByteToMessageDecoder implements Injector {
|
|||||||
|
|
||||||
private void scheduleMainThread(final Object packetCopy) {
|
private void scheduleMainThread(final Object packetCopy) {
|
||||||
// Don't use BukkitExecutors for this - it has a bit of overhead
|
// Don't use BukkitExecutors for this - it has a bit of overhead
|
||||||
Bukkit.getScheduler().scheduleSyncDelayedTask(factory.getPlugin(), new Runnable() {
|
Bukkit.getScheduler().scheduleSyncDelayedTask(factory.getPlugin(), () -> invokeSendPacket(packetCopy));
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
invokeSendPacket(packetCopy);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void decode(ChannelHandlerContext ctx, ByteBuf byteBuffer, List<Object> packets) throws Exception {
|
protected void decode(ChannelHandlerContext ctx, ByteBuf byteBuffer, List<Object> packets) {
|
||||||
byteBuffer.markReaderIndex();
|
|
||||||
DECODE_BUFFER.invoke(vanillaDecoder, ctx, byteBuffer, packets);
|
DECODE_BUFFER.invoke(vanillaDecoder, ctx, byteBuffer, packets);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -546,12 +510,13 @@ public class ChannelInjector extends ByteToMessageDecoder implements Injector {
|
|||||||
if (output != null) {
|
if (output != null) {
|
||||||
if (output.isCancelled()) {
|
if (output.isCancelled()) {
|
||||||
it.remove();
|
it.remove();
|
||||||
continue;
|
} else {
|
||||||
} else if (output.getPacket().getHandle() != input) {
|
if (output.getPacket().getHandle() != input) {
|
||||||
it.set(output.getPacket().getHandle());
|
it.set(output.getPacket().getHandle());
|
||||||
}
|
}
|
||||||
|
|
||||||
finishQueue.addLast(output);
|
finishQueue.addLast(output);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@ -561,11 +526,9 @@ public class ChannelInjector extends ByteToMessageDecoder implements Injector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invoked after our decoder.
|
* Invoked after our decoder
|
||||||
* @param ctx - current context.
|
|
||||||
* @param msg - the current packet.
|
|
||||||
*/
|
*/
|
||||||
protected void finishRead(ChannelHandlerContext ctx, Object msg) {
|
private void finishRead() {
|
||||||
// Assume same order
|
// Assume same order
|
||||||
PacketEvent event = finishQueue.pollFirst();
|
PacketEvent event = finishQueue.pollFirst();
|
||||||
|
|
||||||
@ -583,7 +546,7 @@ public class ChannelInjector extends ByteToMessageDecoder implements Injector {
|
|||||||
* @param packetClass - the packet class.
|
* @param packetClass - the packet class.
|
||||||
* @param packet - the packet.
|
* @param packet - the packet.
|
||||||
*/
|
*/
|
||||||
protected void handleLogin(Class<?> packetClass, Object packet) {
|
private void handleLogin(Class<?> packetClass, Object packet) {
|
||||||
// Try to find the login packet class
|
// Try to find the login packet class
|
||||||
if (PACKET_LOGIN_CLIENT == null) {
|
if (PACKET_LOGIN_CLIENT == null) {
|
||||||
PACKET_LOGIN_CLIENT = PacketType.Login.Client.START.getPacketClass();
|
PACKET_LOGIN_CLIENT = PacketType.Login.Client.START.getPacketClass();
|
||||||
@ -701,15 +664,12 @@ public class ChannelInjector extends ByteToMessageDecoder implements Injector {
|
|||||||
// TODO: Ensure the packet listeners are executed in the channel thread.
|
// TODO: Ensure the packet listeners are executed in the channel thread.
|
||||||
|
|
||||||
// Execute this in the channel thread
|
// Execute this in the channel thread
|
||||||
Runnable action = new Runnable() {
|
Runnable action = () -> {
|
||||||
@Override
|
try {
|
||||||
public void run() {
|
MinecraftMethods.getNetworkManagerReadPacketMethod().invoke(networkManager, null, packet);
|
||||||
try {
|
} catch (Exception e) {
|
||||||
MinecraftMethods.getNetworkManagerReadPacketMethod().invoke(networkManager, null, packet);
|
// Inform the user
|
||||||
} catch (Exception e) {
|
ProtocolLibrary.getErrorReporter().reportMinimal(factory.getPlugin(), "recieveClientPacket", e);
|
||||||
// Inform the user
|
|
||||||
ProtocolLibrary.getErrorReporter().reportMinimal(factory.getPlugin(), "recieveClientPacket", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -821,19 +781,16 @@ public class ChannelInjector extends ByteToMessageDecoder implements Injector {
|
|||||||
// the worker thread is waiting for the main thread to finish executing PlayerQuitEvent.
|
// the worker thread is waiting for the main thread to finish executing PlayerQuitEvent.
|
||||||
//
|
//
|
||||||
// TL;DR: Concurrency is hard.
|
// TL;DR: Concurrency is hard.
|
||||||
executeInChannelThread(new Runnable() {
|
executeInChannelThread(() -> {
|
||||||
@Override
|
String[] handlers = new String[] {
|
||||||
public void run() {
|
"protocol_lib_decoder", "protocol_lib_finish", "protocol_lib_encoder"
|
||||||
String[] handlers = new String[] {
|
};
|
||||||
"protocol_lib_decoder", "protocol_lib_finish", "protocol_lib_encoder"
|
|
||||||
};
|
|
||||||
|
|
||||||
for (String handler : handlers) {
|
for (String handler : handlers) {
|
||||||
try {
|
try {
|
||||||
originalChannel.pipeline().remove(handler);
|
originalChannel.pipeline().remove(handler);
|
||||||
} catch (NoSuchElementException e) {
|
} catch (NoSuchElementException e) {
|
||||||
// Ignore
|
// Ignore
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -856,15 +813,12 @@ public class ChannelInjector extends ByteToMessageDecoder implements Injector {
|
|||||||
* @param command - the command to execute.
|
* @param command - the command to execute.
|
||||||
*/
|
*/
|
||||||
private void executeInChannelThread(final Runnable command) {
|
private void executeInChannelThread(final Runnable command) {
|
||||||
originalChannel.eventLoop().execute(new Runnable() {
|
originalChannel.eventLoop().execute(() -> {
|
||||||
@Override
|
try {
|
||||||
public void run() {
|
command.run();
|
||||||
try {
|
} catch (Exception e) {
|
||||||
command.run();
|
ProtocolLibrary.getErrorReporter().reportDetailed(ChannelInjector.this,
|
||||||
} catch (Exception e) {
|
|
||||||
ProtocolLibrary.getErrorReporter().reportDetailed(ChannelInjector.this,
|
|
||||||
Report.newBuilder(REPORT_CANNOT_EXECUTE_IN_CHANNEL_THREAD).error(e).build());
|
Report.newBuilder(REPORT_CANNOT_EXECUTE_IN_CHANNEL_THREAD).error(e).build());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -875,7 +829,7 @@ public class ChannelInjector extends ByteToMessageDecoder implements Injector {
|
|||||||
* @param clazz - the type.
|
* @param clazz - the type.
|
||||||
* @return The first handler, or NULL.
|
* @return The first handler, or NULL.
|
||||||
*/
|
*/
|
||||||
public static ChannelHandler findChannelHandler(Channel channel, Class<?> clazz) {
|
static ChannelHandler findChannelHandler(Channel channel, Class<?> clazz) {
|
||||||
for (Entry<String, ChannelHandler> entry : channel.pipeline()) {
|
for (Entry<String, ChannelHandler> entry : channel.pipeline()) {
|
||||||
if (clazz.isAssignableFrom(entry.getValue().getClass())) {
|
if (clazz.isAssignableFrom(entry.getValue().getClass())) {
|
||||||
return entry.getValue();
|
return entry.getValue();
|
||||||
@ -891,27 +845,27 @@ public class ChannelInjector extends ByteToMessageDecoder implements Injector {
|
|||||||
public static class ChannelSocketInjector implements SocketInjector {
|
public static class ChannelSocketInjector implements SocketInjector {
|
||||||
private final ChannelInjector injector;
|
private final ChannelInjector injector;
|
||||||
|
|
||||||
public ChannelSocketInjector(ChannelInjector injector) {
|
ChannelSocketInjector(ChannelInjector injector) {
|
||||||
this.injector = Preconditions.checkNotNull(injector, "injector cannot be NULL");
|
this.injector = Preconditions.checkNotNull(injector, "injector cannot be NULL");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Socket getSocket() throws IllegalAccessException {
|
public Socket getSocket() {
|
||||||
return SocketAdapter.adapt((SocketChannel) injector.originalChannel);
|
return SocketAdapter.adapt((SocketChannel) injector.originalChannel);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SocketAddress getAddress() throws IllegalAccessException {
|
public SocketAddress getAddress() {
|
||||||
return injector.originalChannel.remoteAddress();
|
return injector.originalChannel.remoteAddress();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void disconnect(String message) throws InvocationTargetException {
|
public void disconnect(String message) {
|
||||||
injector.disconnect(message);
|
injector.disconnect(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendServerPacket(Object packet, NetworkMarker marker, boolean filtered) throws InvocationTargetException {
|
public void sendServerPacket(Object packet, NetworkMarker marker, boolean filtered) {
|
||||||
injector.sendServerPacket(packet, marker, filtered);
|
injector.sendServerPacket(packet, marker, filtered);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -935,7 +889,7 @@ public class ChannelInjector extends ByteToMessageDecoder implements Injector {
|
|||||||
injector.setPlayer(updatedPlayer);
|
injector.setPlayer(updatedPlayer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChannelInjector getChannelInjector() {
|
ChannelInjector getChannelInjector() {
|
||||||
return injector;
|
return injector;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user