Skip to content

Commit b04fca8

Browse files
committed
Fix packet interception error with ViaVersion (#724)
Thanks to @kennytv and @MedicOP for their help in tracking this bug down. Essentially the decode method we were using could be different depending on when the player logged in, which clashed with PL's static handling of it. Fixes #724 Fixes #791 Fixes #803 Fixes #811 Fixes #813 Fixes #819 ...and probably some others...
1 parent bfa0eee commit b04fca8

File tree

1 file changed

+37
-32
lines changed

1 file changed

+37
-32
lines changed

src/main/java/com/comphenix/protocol/injector/netty/ChannelInjector.java

Lines changed: 37 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -79,23 +79,23 @@ public class ChannelInjector extends ByteToMessageDecoder implements Injector {
7979
// Versioning
8080
private static Class<?> PACKET_SET_PROTOCOL = null;
8181

82-
private static AtomicInteger keyId = new AtomicInteger();
83-
private static AttributeKey<Integer> PROTOCOL_KEY;
82+
private static final AtomicInteger keyId = new AtomicInteger();
83+
private static final AttributeKey<Integer> PROTOCOL_KEY;
8484

8585
static {
8686
PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL-" + keyId.getAndIncrement());
8787
}
8888

8989
// Saved accessors
90-
private static Method DECODE_BUFFER;
91-
private static Method ENCODE_BUFFER;
90+
private Method decodeBuffer;
91+
private Method encodeBuffer;
9292
private static FieldAccessor ENCODER_TYPE_MATCHER;
9393

9494
// For retrieving the protocol
9595
private static FieldAccessor PROTOCOL_ACCESSOR;
9696

9797
// The factory that created this injector
98-
private InjectionFactory factory;
98+
private final InjectionFactory factory;
9999

100100
// The player, or temporary player
101101
private Player player;
@@ -108,10 +108,10 @@ public class ChannelInjector extends ByteToMessageDecoder implements Injector {
108108
// The current network manager and channel
109109
private final Object networkManager;
110110
private final Channel originalChannel;
111-
private VolatileField channelField;
111+
private final VolatileField channelField;
112112

113113
// Known network markers
114-
private Map<Object, NetworkMarker> packetMarker = new WeakHashMap<>();
114+
private final Map<Object, NetworkMarker> packetMarker = new WeakHashMap<>();
115115

116116
/**
117117
* Indicate that this packet has been processed by event listeners.
@@ -134,13 +134,13 @@ public class ChannelInjector extends ByteToMessageDecoder implements Injector {
134134
private ByteToMessageDecoder vanillaDecoder;
135135
private MessageToByteEncoder<Object> vanillaEncoder;
136136

137-
private Deque<PacketEvent> finishQueue = new ArrayDeque<>();
137+
private final Deque<PacketEvent> finishQueue = new ArrayDeque<>();
138138

139139
// The channel listener
140-
private ChannelListener channelListener;
140+
private final ChannelListener channelListener;
141141

142142
// Processing network markers
143-
private NetworkProcessor processor;
143+
private final NetworkProcessor processor;
144144

145145
// Closed
146146
private boolean injected;
@@ -178,6 +178,24 @@ public int getProtocolVersion() {
178178
return value != null ? value : MinecraftProtocolVersion.getCurrentVersion();
179179
}
180180

181+
private void updateBufferMethods() {
182+
try {
183+
decodeBuffer = vanillaDecoder.getClass().getDeclaredMethod("decode",
184+
ChannelHandlerContext.class, ByteBuf.class, List.class);
185+
decodeBuffer.setAccessible(true);
186+
} catch (NoSuchMethodException ex) {
187+
throw new IllegalArgumentException("Unable to find decode method in " + vanillaDecoder.getClass());
188+
}
189+
190+
try {
191+
encodeBuffer = vanillaEncoder.getClass().getDeclaredMethod("encode",
192+
ChannelHandlerContext.class, Object.class, ByteBuf.class);
193+
encodeBuffer.setAccessible(true);
194+
} catch (NoSuchMethodException ex) {
195+
throw new IllegalArgumentException("Unable to find encode method in " + vanillaEncoder.getClass());
196+
}
197+
}
198+
181199
@Override
182200
@SuppressWarnings("unchecked")
183201
public boolean inject() {
@@ -212,25 +230,7 @@ public boolean inject() {
212230
throw new IllegalArgumentException("Unable to find vanilla encoder in " + originalChannel.pipeline());
213231
patchEncoder(vanillaEncoder);
214232

215-
if (DECODE_BUFFER == null) {
216-
try {
217-
DECODE_BUFFER = vanillaDecoder.getClass().getDeclaredMethod("decode",
218-
ChannelHandlerContext.class, ByteBuf.class, List.class);
219-
DECODE_BUFFER.setAccessible(true);
220-
} catch (NoSuchMethodException ex) {
221-
throw new IllegalArgumentException("Unable to find decode method in " + vanillaDecoder.getClass());
222-
}
223-
}
224-
225-
if (ENCODE_BUFFER == null) {
226-
try {
227-
ENCODE_BUFFER = vanillaEncoder.getClass().getDeclaredMethod("encode",
228-
ChannelHandlerContext.class, Object.class, ByteBuf.class);
229-
ENCODE_BUFFER.setAccessible(true);
230-
} catch (NoSuchMethodException ex) {
231-
throw new IllegalArgumentException("Unable to find encode method in " + vanillaEncoder.getClass());
232-
}
233-
}
233+
updateBufferMethods();
234234

235235
// Intercept sent packets
236236
MessageToByteEncoder<Object> protocolEncoder = new MessageToByteEncoder<Object>() {
@@ -447,7 +447,7 @@ private void encode(ChannelHandlerContext ctx, Object packet, ByteBuf output) th
447447
// Process output handler
448448
if (packet != null && event != null && NetworkMarker.hasOutputHandlers(marker)) {
449449
ByteBuf packetBuffer = ctx.alloc().buffer();
450-
ENCODE_BUFFER.invoke(vanillaEncoder, ctx, packet, packetBuffer);
450+
encodeBuffer.invoke(vanillaEncoder, ctx, packet, packetBuffer);
451451

452452
// Let each handler prepare the actual output
453453
byte[] data = processor.processOutput(event, marker, getBytes(packetBuffer));
@@ -470,7 +470,7 @@ private void encode(ChannelHandlerContext ctx, Object packet, ByteBuf output) th
470470
// Attempt to handle the packet nevertheless
471471
if (packet != null) {
472472
try {
473-
ENCODE_BUFFER.invoke(vanillaEncoder, ctx, packet, output);
473+
encodeBuffer.invoke(vanillaEncoder, ctx, packet, output);
474474
} catch (InvocationTargetException ex) {
475475
if (ex.getCause() instanceof Exception) {
476476
//noinspection ThrowFromFinallyBlock
@@ -510,7 +510,12 @@ private void scheduleMainThread(final Object packetCopy) {
510510
@Override
511511
protected void decode(ChannelHandlerContext ctx, ByteBuf byteBuffer, List<Object> packets) throws Exception {
512512
try {
513-
DECODE_BUFFER.invoke(vanillaDecoder, ctx, byteBuffer, packets);
513+
try {
514+
decodeBuffer.invoke(vanillaDecoder, ctx, byteBuffer, packets);
515+
} catch (IllegalArgumentException ex) {
516+
updateBufferMethods();
517+
decodeBuffer.invoke(vanillaDecoder, ctx, byteBuffer, packets);
518+
}
514519

515520
// Reset queue
516521
finishQueue.clear();

0 commit comments

Comments
 (0)