diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/netty/MinecraftVarintFrameDecoder.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/netty/MinecraftVarintFrameDecoder.java index d81f53f5b..675ddf7f7 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/netty/MinecraftVarintFrameDecoder.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/netty/MinecraftVarintFrameDecoder.java @@ -44,17 +44,24 @@ public class MinecraftVarintFrameDecoder extends ByteToMessageDecoder { if (varintEnd == -1) { // We tried to go beyond the end of the buffer. This is probably a good sign that the // buffer was too short to hold a proper varint. + if (reader.getResult() == DecodeResult.RUN_OF_ZEROES) { + // Special case where the entire packet is just a run of zeroes. We ignore them all. + in.clear(); + } return; } - if (reader.getResult() == DecodeResult.SUCCESS) { + if (reader.getResult() == DecodeResult.RUN_OF_ZEROES) { + // this will return to the point where the next varint starts + in.readerIndex(varintEnd); + } else if (reader.getResult() == DecodeResult.SUCCESS) { int readVarint = reader.getReadVarint(); int bytesRead = reader.getBytesRead(); if (readVarint < 0) { in.clear(); throw BAD_LENGTH_CACHED; } else if (readVarint == 0) { - // skip over the empty packet and ignore it + // skip over the empty packet(s) and ignore it in.readerIndex(varintEnd + 1); } else { int minimumRead = bytesRead + readVarint; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/netty/VarintByteDecoder.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/netty/VarintByteDecoder.java index c50672f18..a67371bea 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/netty/VarintByteDecoder.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/netty/VarintByteDecoder.java @@ -27,6 +27,14 @@ class VarintByteDecoder implements ByteProcessor { @Override public boolean process(byte k) { + if (k == 0 && bytesRead == 0) { + // tentatively say it's invalid, but there's a possibility of redemption + result = DecodeResult.RUN_OF_ZEROES; + return true; + } + if (result == DecodeResult.RUN_OF_ZEROES) { + return false; + } readVarint |= (k & 0x7F) << bytesRead++ * 7; if (bytesRead > 3) { result = DecodeResult.TOO_BIG; @@ -54,6 +62,7 @@ class VarintByteDecoder implements ByteProcessor { public enum DecodeResult { SUCCESS, TOO_SHORT, - TOO_BIG + TOO_BIG, + RUN_OF_ZEROES } } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/AvailableCommands.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/AvailableCommands.java index b40d13f00..a154a5fae 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/AvailableCommands.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/AvailableCommands.java @@ -122,6 +122,9 @@ public class AvailableCommands implements MinecraftPacket { if (!idMappings.containsKey(child)) { idMappings.put(child, idMappings.size()); childrenQueue.addAll(child.getChildren()); + if (child.getRedirect() != null) { + childrenQueue.add(child.getRedirect()); + } } }