From bc92a3b1a1f14ed5b31b8baa82e17b4ede1d8bdf Mon Sep 17 00:00:00 2001 From: Troy Frew Date: Tue, 15 Nov 2016 10:31:04 -0500 Subject: [PATCH] 1.7.x Protocol Patch diff --git a/protocol/src/main/java/io/github/waterfallmc/travertine/protocol/MultiVersionPacketV17.java b/protocol/src/main/java/io/github/waterfallmc/travertine/protocol/MultiVersionPacketV17.java new file mode 100644 index 000000000..90064112e --- /dev/null +++ b/protocol/src/main/java/io/github/waterfallmc/travertine/protocol/MultiVersionPacketV17.java @@ -0,0 +1,90 @@ +package io.github.waterfallmc.travertine.protocol; + +import com.google.common.base.Preconditions; +import io.netty.buffer.ByteBuf; + +import net.md_5.bungee.protocol.DefinedPacket; +import net.md_5.bungee.protocol.ProtocolConstants; + +public abstract class MultiVersionPacketV17 extends DefinedPacket +{ + + protected void v17Read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) + { + v17Read( buf ); + } + + @Override + public void read0(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) + { + switch ( protocolVersion ) + { + case ProtocolConstants.MINECRAFT_1_7_2: + case ProtocolConstants.MINECRAFT_1_7_6: + v17Read(buf, direction, protocolVersion); + break; + default: + read(buf, direction, protocolVersion); + break; + } + } + + protected void v17Write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) + { + v17Write( buf ); + } + + @Override + public void write0(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) + { + switch ( protocolVersion ) + { + case ProtocolConstants.MINECRAFT_1_7_2: + case ProtocolConstants.MINECRAFT_1_7_6: + v17Write(buf, direction, protocolVersion); + break; + default: + write(buf, direction, protocolVersion); + break; + } + } + protected void v17Read(ByteBuf buf) + { + throw new UnsupportedOperationException( "Packet must implement read method" ); + } + + protected void v17Write(ByteBuf buf) + { + throw new UnsupportedOperationException( "Packet must implement write method" ); + } + + public static void v17writeArray(byte[] b, ByteBuf buf, boolean allowExtended) + { + // (Integer.MAX_VALUE & 0x1FFF9A ) = 2097050 - Forge's current upper limit + if ( allowExtended ) + { + Preconditions.checkArgument( b.length <= ( Integer.MAX_VALUE & 0x1FFF9A ), "Cannot send array longer than 2097050 (got %s bytes)", b.length ); + } else + { + Preconditions.checkArgument( b.length <= Short.MAX_VALUE, "Cannot send array longer than Short.MAX_VALUE (got %s bytes)", b.length ); + } + // Write a 2 or 3 byte number that represents the length of the packet. (3 byte "shorts" for Forge only) + // No vanilla packet should give a 3 byte packet, this method will still retain vanilla behaviour. + writeVarShort( buf, b.length ); + buf.writeBytes( b ); + } + + public static byte[] v17readArray(ByteBuf buf) + { + // Read in a 2 or 3 byte number that represents the length of the packet. (3 byte "shorts" for Forge only) + // No vanilla packet should give a 3 byte packet, this method will still retain vanilla behaviour. + int len = readVarShort( buf ); + + // (Integer.MAX_VALUE & 0x1FFF9A ) = 2097050 - Forge's current upper limit + Preconditions.checkArgument( len <= ( Integer.MAX_VALUE & 0x1FFF9A ), "Cannot receive array longer than 2097050 (got %s bytes)", len ); + + byte[] ret = new byte[ len ]; + buf.readBytes( ret ); + return ret; + } +} diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/DefinedPacket.java b/protocol/src/main/java/net/md_5/bungee/protocol/DefinedPacket.java index 31a954950..93d17f6b5 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/DefinedPacket.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/DefinedPacket.java @@ -266,6 +266,11 @@ public abstract class DefinedPacket read( buf ); } + public void read0(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) + { + read( buf, direction, protocolVersion ); + } + public void write(ByteBuf buf) { throw new UnsupportedOperationException( "Packet must implement write method" ); @@ -276,6 +281,11 @@ public abstract class DefinedPacket write( buf ); } + public void write0(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) + { + write( buf, direction, protocolVersion ); + } + public abstract void handle(AbstractPacketHandler handler) throws Exception; @Override diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/MinecraftDecoder.java b/protocol/src/main/java/net/md_5/bungee/protocol/MinecraftDecoder.java index 01d35f41a..52f602763 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/MinecraftDecoder.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/MinecraftDecoder.java @@ -57,7 +57,7 @@ public class MinecraftDecoder extends MessageToMessageDecoder { packetTypeInfo = packet.getClass(); doLengthSanityChecks(in, packet, prot.getDirection(), packetId); // Waterfall: Additional DoS mitigations - packet.read( in, prot.getDirection(), protocolVersion ); + packet.read0( in, prot.getDirection(), protocolVersion ); if ( in.isReadable() ) { diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/MinecraftEncoder.java b/protocol/src/main/java/net/md_5/bungee/protocol/MinecraftEncoder.java index d4b038434..9aac7ca9f 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/MinecraftEncoder.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/MinecraftEncoder.java @@ -21,6 +21,6 @@ public class MinecraftEncoder extends MessageToByteEncoder { Protocol.DirectionData prot = ( server ) ? protocol.TO_CLIENT : protocol.TO_SERVER; DefinedPacket.writeVarInt( prot.getId( msg.getClass(), protocolVersion ), out ); - msg.write( out, prot.getDirection(), protocolVersion ); + msg.write0( out, prot.getDirection(), protocolVersion ); } } diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/Protocol.java b/protocol/src/main/java/net/md_5/bungee/protocol/Protocol.java index 0dffc8d23..ff671706d 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/Protocol.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/Protocol.java @@ -55,7 +55,7 @@ public enum Protocol TO_SERVER.registerPacket( Handshake.class, Handshake::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_8, 0x00 ) + map( ProtocolConstants.MINECRAFT_1_7_2, 0x00 ) // Travertine ); } }, @@ -67,7 +67,7 @@ public enum Protocol TO_CLIENT.registerPacket( KeepAlive.class, KeepAlive::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_8, 0x00 ), + map( ProtocolConstants.MINECRAFT_1_7_2, 0x00 ), // Travertine map( ProtocolConstants.MINECRAFT_1_9, 0x1F ), map( ProtocolConstants.MINECRAFT_1_13, 0x21 ), map( ProtocolConstants.MINECRAFT_1_14, 0x20 ), @@ -78,7 +78,7 @@ public enum Protocol TO_CLIENT.registerPacket( Login.class, Login::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_8, 0x01 ), + map( ProtocolConstants.MINECRAFT_1_7_2, 0x01 ), // Travertine map( ProtocolConstants.MINECRAFT_1_9, 0x23 ), map( ProtocolConstants.MINECRAFT_1_13, 0x25 ), map( ProtocolConstants.MINECRAFT_1_15, 0x26 ), @@ -88,7 +88,7 @@ public enum Protocol TO_CLIENT.registerPacket( Chat.class, Chat::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_8, 0x02 ), + map( ProtocolConstants.MINECRAFT_1_7_2, 0x02 ), // Travertine map( ProtocolConstants.MINECRAFT_1_9, 0x0F ), map( ProtocolConstants.MINECRAFT_1_13, 0x0E ), map( ProtocolConstants.MINECRAFT_1_15, 0x0F ), @@ -97,7 +97,7 @@ public enum Protocol TO_CLIENT.registerPacket( Respawn.class, Respawn::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_8, 0x07 ), + map( ProtocolConstants.MINECRAFT_1_7_2, 0x07 ), // Travertine map( ProtocolConstants.MINECRAFT_1_9, 0x33 ), map( ProtocolConstants.MINECRAFT_1_12, 0x34 ), map( ProtocolConstants.MINECRAFT_1_12_1, 0x35 ), @@ -118,20 +118,19 @@ public enum Protocol TO_CLIENT.registerPacket( EntityEffect.class, EntityEffect::new, // Waterfall - speed up packet construction - map(ProtocolConstants.MINECRAFT_1_8, 0x1D), + map(ProtocolConstants.MINECRAFT_1_7_2, 0x1D), // Travertine map(ProtocolConstants.MINECRAFT_1_9, Integer.MIN_VALUE) ); TO_CLIENT.registerPacket( EntityRemoveEffect.class, EntityRemoveEffect::new, // Waterfall - speed up packet construction - map(ProtocolConstants.MINECRAFT_1_8, 0x1E), + map(ProtocolConstants.MINECRAFT_1_7_2, 0x1E), // Travertine map(ProtocolConstants.MINECRAFT_1_9, Integer.MIN_VALUE) ); // Waterfall end TO_CLIENT.registerPacket( PlayerListItem.class, // PlayerInfo - PlayerListItem::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_8, 0x38 ), + map( ProtocolConstants.MINECRAFT_1_7_2, 0x38 ), // Travertine map( ProtocolConstants.MINECRAFT_1_9, 0x2D ), map( ProtocolConstants.MINECRAFT_1_12_1, 0x2E ), map( ProtocolConstants.MINECRAFT_1_13, 0x30 ), @@ -143,7 +142,7 @@ public enum Protocol TO_CLIENT.registerPacket( TabCompleteResponse.class, TabCompleteResponse::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_8, 0x3A ), + map( ProtocolConstants.MINECRAFT_1_7_2, 0x3A ), // Travertine map( ProtocolConstants.MINECRAFT_1_9, 0x0E ), map( ProtocolConstants.MINECRAFT_1_13, 0x10 ), map( ProtocolConstants.MINECRAFT_1_15, 0x11 ), @@ -153,7 +152,7 @@ public enum Protocol TO_CLIENT.registerPacket( ScoreboardObjective.class, ScoreboardObjective::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_8, 0x3B ), + map( ProtocolConstants.MINECRAFT_1_7_2, 0x3B ), // Travertine map( ProtocolConstants.MINECRAFT_1_9, 0x3F ), map( ProtocolConstants.MINECRAFT_1_12, 0x41 ), map( ProtocolConstants.MINECRAFT_1_12_1, 0x42 ), @@ -164,7 +163,7 @@ public enum Protocol TO_CLIENT.registerPacket( ScoreboardScore.class, ScoreboardScore::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_8, 0x3C ), + map( ProtocolConstants.MINECRAFT_1_7_2, 0x3C ), // Travertine map( ProtocolConstants.MINECRAFT_1_9, 0x42 ), map( ProtocolConstants.MINECRAFT_1_12, 0x44 ), map( ProtocolConstants.MINECRAFT_1_12_1, 0x45 ), @@ -175,7 +174,7 @@ public enum Protocol TO_CLIENT.registerPacket( ScoreboardDisplay.class, ScoreboardDisplay::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_8, 0x3D ), + map( ProtocolConstants.MINECRAFT_1_7_2, 0x3D ), // Travertine map( ProtocolConstants.MINECRAFT_1_9, 0x38 ), map( ProtocolConstants.MINECRAFT_1_12, 0x3A ), map( ProtocolConstants.MINECRAFT_1_12_1, 0x3B ), @@ -186,7 +185,7 @@ public enum Protocol TO_CLIENT.registerPacket( Team.class, Team::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_8, 0x3E ), + map( ProtocolConstants.MINECRAFT_1_7_2, 0x3E ), // Travertine map( ProtocolConstants.MINECRAFT_1_9, 0x41 ), map( ProtocolConstants.MINECRAFT_1_12, 0x43 ), map( ProtocolConstants.MINECRAFT_1_12_1, 0x44 ), @@ -197,7 +196,7 @@ public enum Protocol TO_CLIENT.registerPacket( PluginMessage.class, PluginMessage::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_8, 0x3F ), + map( ProtocolConstants.MINECRAFT_1_7_2, 0x3F ), // Travertine map( ProtocolConstants.MINECRAFT_1_9, 0x18 ), map( ProtocolConstants.MINECRAFT_1_13, 0x19 ), map( ProtocolConstants.MINECRAFT_1_14, 0x18 ), @@ -208,7 +207,7 @@ public enum Protocol TO_CLIENT.registerPacket( Kick.class, Kick::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_8, 0x40 ), + map( ProtocolConstants.MINECRAFT_1_7_2, 0x40 ), // Travertine map( ProtocolConstants.MINECRAFT_1_9, 0x1A ), map( ProtocolConstants.MINECRAFT_1_13, 0x1B ), map( ProtocolConstants.MINECRAFT_1_14, 0x1A ), @@ -219,7 +218,7 @@ public enum Protocol TO_CLIENT.registerPacket( Title.class, Title::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_8, 0x45 ), + map( ProtocolConstants.MINECRAFT_1_7_2, 0x45 ), // Travertine map( ProtocolConstants.MINECRAFT_1_12, 0x47 ), map( ProtocolConstants.MINECRAFT_1_12_1, 0x48 ), map( ProtocolConstants.MINECRAFT_1_13, 0x4B ), @@ -230,7 +229,7 @@ public enum Protocol TO_CLIENT.registerPacket( PlayerListHeaderFooter.class, PlayerListHeaderFooter::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_8, 0x47 ), + map( ProtocolConstants.MINECRAFT_1_7_2, 0x47 ), // Travertine map( ProtocolConstants.MINECRAFT_1_9, 0x48 ), map( ProtocolConstants.MINECRAFT_1_9_4, 0x47 ), map( ProtocolConstants.MINECRAFT_1_12, 0x49 ), @@ -243,7 +242,7 @@ public enum Protocol TO_CLIENT.registerPacket( EntityStatus.class, EntityStatus::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_8, 0x1A ), + map( ProtocolConstants.MINECRAFT_1_7_2, 0x1A ), // Travertine map( ProtocolConstants.MINECRAFT_1_9, 0x1B ), map( ProtocolConstants.MINECRAFT_1_13, 0x1C ), map( ProtocolConstants.MINECRAFT_1_14, 0x1B ), @@ -277,7 +276,7 @@ public enum Protocol TO_SERVER.registerPacket( KeepAlive.class, KeepAlive::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_8, 0x00 ), + map( ProtocolConstants.MINECRAFT_1_7_2, 0x00 ), // Travertine map( ProtocolConstants.MINECRAFT_1_9, 0x0B ), map( ProtocolConstants.MINECRAFT_1_12, 0x0C ), map( ProtocolConstants.MINECRAFT_1_12_1, 0x0B ), @@ -288,7 +287,7 @@ public enum Protocol TO_SERVER.registerPacket( Chat.class, Chat::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_8, 0x01 ), + map( ProtocolConstants.MINECRAFT_1_7_2, 0x01 ), // Travertine map( ProtocolConstants.MINECRAFT_1_9, 0x02 ), map( ProtocolConstants.MINECRAFT_1_12, 0x03 ), map( ProtocolConstants.MINECRAFT_1_12_1, 0x02 ), @@ -297,7 +296,7 @@ public enum Protocol TO_SERVER.registerPacket( TabCompleteRequest.class, TabCompleteRequest::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_8, 0x14 ), + map( ProtocolConstants.MINECRAFT_1_7_2, 0x14 ), // Travertine map( ProtocolConstants.MINECRAFT_1_9, 0x01 ), map( ProtocolConstants.MINECRAFT_1_12, 0x02 ), map( ProtocolConstants.MINECRAFT_1_12_1, 0x01 ), @@ -307,7 +306,7 @@ public enum Protocol TO_SERVER.registerPacket( ClientSettings.class, ClientSettings::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_8, 0x15 ), + map( ProtocolConstants.MINECRAFT_1_7_2, 0x15 ), // Travertine map( ProtocolConstants.MINECRAFT_1_9, 0x04 ), map( ProtocolConstants.MINECRAFT_1_12, 0x05 ), map( ProtocolConstants.MINECRAFT_1_12_1, 0x04 ), @@ -316,7 +315,7 @@ public enum Protocol TO_SERVER.registerPacket( PluginMessage.class, PluginMessage::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_8, 0x17 ), + map( ProtocolConstants.MINECRAFT_1_7_2, 0x17 ), // Travertine map( ProtocolConstants.MINECRAFT_1_9, 0x09 ), map( ProtocolConstants.MINECRAFT_1_12, 0x0A ), map( ProtocolConstants.MINECRAFT_1_12_1, 0x09 ), @@ -333,23 +332,23 @@ public enum Protocol TO_CLIENT.registerPacket( StatusResponse.class, StatusResponse::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_8, 0x00 ) + map( ProtocolConstants.MINECRAFT_1_7_2, 0x00 ) // Travertine ); TO_CLIENT.registerPacket( PingPacket.class, PingPacket::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_8, 0x01 ) + map( ProtocolConstants.MINECRAFT_1_7_2, 0x01 ) // Travertine ); TO_SERVER.registerPacket( StatusRequest.class, StatusRequest::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_8, 0x00 ) + map( ProtocolConstants.MINECRAFT_1_7_2, 0x00 ) // Travertine ); TO_SERVER.registerPacket( PingPacket.class, PingPacket::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_8, 0x01 ) + map( ProtocolConstants.MINECRAFT_1_7_2, 0x01 ) // Travertine ); } }, @@ -361,22 +360,22 @@ public enum Protocol TO_CLIENT.registerPacket( Kick.class, Kick::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_8, 0x00 ) + map( ProtocolConstants.MINECRAFT_1_7_2, 0x00 ) // Travertine ); TO_CLIENT.registerPacket( EncryptionRequest.class, EncryptionRequest::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_8, 0x01 ) + map( ProtocolConstants.MINECRAFT_1_7_2, 0x01 ) // Travertine ); TO_CLIENT.registerPacket( LoginSuccess.class, LoginSuccess::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_8, 0x02 ) + map( ProtocolConstants.MINECRAFT_1_7_2, 0x02 ) // Travertine ); TO_CLIENT.registerPacket( SetCompression.class, SetCompression::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_8, 0x03 ) + map( ProtocolConstants.MINECRAFT_1_7_2, 0x03 ) // Travertine ); TO_CLIENT.registerPacket( LoginPayloadRequest.class, @@ -387,12 +386,12 @@ public enum Protocol TO_SERVER.registerPacket( LoginRequest.class, LoginRequest::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_8, 0x00 ) + map( ProtocolConstants.MINECRAFT_1_7_2, 0x00 ) // Travertine ); TO_SERVER.registerPacket( EncryptionResponse.class, EncryptionResponse::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_8, 0x01 ) + map( ProtocolConstants.MINECRAFT_1_7_2, 0x01 ) // Travertine ); TO_SERVER.registerPacket( LoginPayloadResponse.class, @@ -512,7 +511,11 @@ public enum Protocol } if ( !hasPacket(id, supportsForge) ) { - throw new BadPacketException( "Packet with id " + id + " outside of range " ); + if ( ProtocolConstants.isBeforeOrEq( version, ProtocolConstants.MINECRAFT_1_7_6 ) ) { + return null; + } else { + throw new BadPacketException( "Packet with id " + id + " outside of range " ); + } } java.util.function.Supplier constructor = protocolData.packetConstructors[id]; // Waterfall - speed up packet construction diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/ProtocolConstants.java b/protocol/src/main/java/net/md_5/bungee/protocol/ProtocolConstants.java index 2202c4d3d..6600185b5 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/ProtocolConstants.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/ProtocolConstants.java @@ -6,6 +6,8 @@ import java.util.List; public class ProtocolConstants { + public static final int MINECRAFT_1_7_2 = 4; + public static final int MINECRAFT_1_7_6 = 5; public static final int MINECRAFT_1_8 = 47; public static final int MINECRAFT_1_9 = 107; public static final int MINECRAFT_1_9_1 = 108; @@ -34,6 +36,7 @@ public class ProtocolConstants public static final int MINECRAFT_1_16_3 = 753; public static final int MINECRAFT_1_16_4 = 754; public static final List SUPPORTED_VERSIONS = Arrays.asList( + "1.7.x", "1.8.x", "1.9.x", "1.10.x", @@ -45,6 +48,8 @@ public class ProtocolConstants "1.16.x" ); public static final List SUPPORTED_VERSION_IDS = Arrays.asList( + ProtocolConstants.MINECRAFT_1_7_2, + ProtocolConstants.MINECRAFT_1_7_6, ProtocolConstants.MINECRAFT_1_8, ProtocolConstants.MINECRAFT_1_9, ProtocolConstants.MINECRAFT_1_9_1, diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/Varint21FrameDecoder.java b/protocol/src/main/java/net/md_5/bungee/protocol/Varint21FrameDecoder.java index c0d371426..a07e25b1f 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/Varint21FrameDecoder.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/Varint21FrameDecoder.java @@ -6,10 +6,12 @@ import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ByteToMessageDecoder; import io.netty.handler.codec.CorruptedFrameException; import java.util.List; +import java.util.concurrent.atomic.AtomicLong; public class Varint21FrameDecoder extends ByteToMessageDecoder { + private AtomicLong lastEmptyPacket = new AtomicLong(0); // Travertine private static boolean DIRECT_WARNING; @Override @@ -44,7 +46,15 @@ public class Varint21FrameDecoder extends ByteToMessageDecoder // Waterfall end if ( false && length == 0) // Waterfall - ignore { - throw new CorruptedFrameException( "Empty Packet!" ); + // Travertine start - vanilla 1.7 client sometimes sends empty packets. + long currentTime = System.currentTimeMillis(); + long lastEmptyPacket = this.lastEmptyPacket.getAndSet(currentTime); + + if (currentTime - lastEmptyPacket < 50L) + { + throw new CorruptedFrameException( "Too many empty packets" ); + } + // Travertine end } if ( in.readableBytes() < length ) diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/packet/Chat.java b/protocol/src/main/java/net/md_5/bungee/protocol/packet/Chat.java index 828a5dbe6..195ec0886 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/packet/Chat.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/packet/Chat.java @@ -1,5 +1,6 @@ package net.md_5.bungee.protocol.packet; +import io.github.waterfallmc.travertine.protocol.MultiVersionPacketV17; import io.netty.buffer.ByteBuf; import java.util.UUID; import lombok.Data; @@ -12,7 +13,7 @@ import net.md_5.bungee.protocol.ProtocolConstants; @Data @NoArgsConstructor @EqualsAndHashCode(callSuper = false) -public class Chat extends DefinedPacket +public class Chat extends MultiVersionPacketV17 { private static final UUID EMPTY_UUID = new UUID( 0L, 0L ); @@ -36,6 +37,13 @@ public class Chat extends DefinedPacket this.position = position; this.sender = sender == null ? EMPTY_UUID : sender; } + // Travertine start + @Override + public void v17Read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) + { + message = readString( buf ); + } + // Travertine end @Override public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) @@ -56,6 +64,14 @@ public class Chat extends DefinedPacket } } + // Travertine start + @Override + public void v17Write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) + { + writeString( message, buf ); + } + // Travertine end + @Override public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) { diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/packet/ClientSettings.java b/protocol/src/main/java/net/md_5/bungee/protocol/packet/ClientSettings.java index 9daf7a737..b7640fcbf 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/packet/ClientSettings.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/packet/ClientSettings.java @@ -1,5 +1,7 @@ package net.md_5.bungee.protocol.packet; +import io.github.waterfallmc.travertine.protocol.MultiVersionPacketV17; +import net.md_5.bungee.protocol.DefinedPacket; import io.netty.buffer.ByteBuf; import lombok.AllArgsConstructor; import lombok.Data; @@ -13,7 +15,7 @@ import net.md_5.bungee.protocol.ProtocolConstants; @NoArgsConstructor @AllArgsConstructor @EqualsAndHashCode(callSuper = false) -public class ClientSettings extends DefinedPacket +public class ClientSettings extends MultiVersionPacketV17 { private String locale; @@ -24,6 +26,19 @@ public class ClientSettings extends DefinedPacket private byte skinParts; private int mainHand; + // Travertine start + @Override + public void v17Read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) + { + locale = readString( buf ); + viewDistance = buf.readByte(); + chatFlags = buf.readUnsignedByte(); + chatColours = buf.readBoolean(); + skinParts = buf.readByte(); + difficulty = buf.readByte(); + } + // Travertine end + @Override public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) { @@ -58,6 +73,19 @@ public class ClientSettings extends DefinedPacket } } + // Travertine start + @Override + public void v17Write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) + { + writeString( locale, buf ); + buf.writeByte( viewDistance ); + buf.writeByte( chatFlags ); + buf.writeBoolean( chatColours ); + buf.writeByte( skinParts ); + buf.writeByte( difficulty ); + } + // Travertine end + @Override public void handle(AbstractPacketHandler handler) throws Exception { diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/packet/EncryptionRequest.java b/protocol/src/main/java/net/md_5/bungee/protocol/packet/EncryptionRequest.java index a29524ca8..8d9f4ccb3 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/packet/EncryptionRequest.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/packet/EncryptionRequest.java @@ -1,25 +1,35 @@ package net.md_5.bungee.protocol.packet; +import io.github.waterfallmc.travertine.protocol.MultiVersionPacketV17; import io.netty.buffer.ByteBuf; import lombok.AllArgsConstructor; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; import net.md_5.bungee.protocol.AbstractPacketHandler; -import net.md_5.bungee.protocol.DefinedPacket; import net.md_5.bungee.protocol.ProtocolConstants; @Data @NoArgsConstructor @AllArgsConstructor @EqualsAndHashCode(callSuper = false) -public class EncryptionRequest extends DefinedPacket +public class EncryptionRequest extends MultiVersionPacketV17 { private String serverId; private byte[] publicKey; private byte[] verifyToken; + // Travertine start + @Override + public void v17Read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) + { + serverId = readString( buf ); + publicKey = v17readArray( buf ); + verifyToken = v17readArray( buf ); + } + // Travertine end + @Override public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) { @@ -28,6 +38,16 @@ public class EncryptionRequest extends DefinedPacket verifyToken = readArray( buf ); } + // Travertine start + @Override + public void v17Write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) + { + writeString( serverId, buf ); + v17writeArray( publicKey, buf, false ); + v17writeArray( verifyToken, buf, false ); + } + // Travertine end + @Override public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) { diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/packet/EncryptionResponse.java b/protocol/src/main/java/net/md_5/bungee/protocol/packet/EncryptionResponse.java index 53575ce0e..1a41da75a 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/packet/EncryptionResponse.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/packet/EncryptionResponse.java @@ -1,5 +1,6 @@ package net.md_5.bungee.protocol.packet; +import io.github.waterfallmc.travertine.protocol.MultiVersionPacketV17; import io.netty.buffer.ByteBuf; import lombok.AllArgsConstructor; import lombok.Data; @@ -13,12 +14,21 @@ import net.md_5.bungee.protocol.ProtocolConstants; @NoArgsConstructor @AllArgsConstructor @EqualsAndHashCode(callSuper = false) -public class EncryptionResponse extends DefinedPacket +public class EncryptionResponse extends MultiVersionPacketV17 { private byte[] sharedSecret; private byte[] verifyToken; + // Travertine start + @Override + public void v17Read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) + { + sharedSecret = v17readArray( buf ); + verifyToken = v17readArray( buf ); + } + // Travertine end + @Override public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) { @@ -26,6 +36,15 @@ public class EncryptionResponse extends DefinedPacket verifyToken = readArray( buf, 128 ); } + // Travertine start + @Override + public void v17Write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) + { + v17writeArray( sharedSecret, buf, false ); + v17writeArray( verifyToken, buf, false ); + } + // Travertine end + @Override public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) { diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/packet/EntityEffect.java b/protocol/src/main/java/net/md_5/bungee/protocol/packet/EntityEffect.java index d11a9ea9d..07fc21b65 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/packet/EntityEffect.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/packet/EntityEffect.java @@ -1,18 +1,19 @@ package net.md_5.bungee.protocol.packet; +import io.github.waterfallmc.travertine.protocol.MultiVersionPacketV17; import io.netty.buffer.ByteBuf; import lombok.AllArgsConstructor; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; import net.md_5.bungee.protocol.AbstractPacketHandler; -import net.md_5.bungee.protocol.DefinedPacket; +import net.md_5.bungee.protocol.ProtocolConstants; @Data @NoArgsConstructor @AllArgsConstructor @EqualsAndHashCode(callSuper = false) -public class EntityEffect extends DefinedPacket { +public class EntityEffect extends MultiVersionPacketV17 { private int entityId; private int effectId; @@ -20,6 +21,14 @@ public class EntityEffect extends DefinedPacket { private int duration; private boolean hideParticles; + @Override + protected void v17Read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) { + this.entityId = buf.readInt(); + this.effectId = buf.readUnsignedByte(); + this.amplifier = buf.readUnsignedByte(); + this.duration = buf.readShort(); + } + @Override public void read(ByteBuf buf) { this.entityId = readVarInt(buf); @@ -29,6 +38,14 @@ public class EntityEffect extends DefinedPacket { this.hideParticles = buf.readBoolean(); } + @Override + protected void v17Write(ByteBuf buf) { + buf.writeInt(effectId); + buf.writeByte(effectId); + buf.writeByte(amplifier); + buf.writeShort(duration); + } + @Override public void write(ByteBuf buf) { writeVarInt(this.entityId, buf); diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/packet/EntityRemoveEffect.java b/protocol/src/main/java/net/md_5/bungee/protocol/packet/EntityRemoveEffect.java index 7ed2dc3ab..9f8d56fc7 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/packet/EntityRemoveEffect.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/packet/EntityRemoveEffect.java @@ -1,18 +1,18 @@ package net.md_5.bungee.protocol.packet; +import io.github.waterfallmc.travertine.protocol.MultiVersionPacketV17; import io.netty.buffer.ByteBuf; import lombok.AllArgsConstructor; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; import net.md_5.bungee.protocol.AbstractPacketHandler; -import net.md_5.bungee.protocol.DefinedPacket; @Data @NoArgsConstructor @AllArgsConstructor @EqualsAndHashCode(callSuper = false) -public class EntityRemoveEffect extends DefinedPacket { +public class EntityRemoveEffect extends MultiVersionPacketV17 { private int entityId; private int effectId; @@ -23,9 +23,15 @@ public class EntityRemoveEffect extends DefinedPacket { this.effectId = buf.readUnsignedByte(); } + @Override + protected void v17Read(ByteBuf buf) { + this.entityId = buf.readInt(); + this.effectId = buf.readUnsignedByte(); + } + @Override public void write(ByteBuf buf) { - writeVarInt(this.entityId, buf); + writeVarInt(entityId, buf); buf.writeByte(effectId); } @@ -33,4 +39,10 @@ public class EntityRemoveEffect extends DefinedPacket { public void handle(AbstractPacketHandler handler) throws Exception { handler.handle(this); } + + @Override + protected void v17Write(ByteBuf buf) { + buf.writeInt(entityId); + buf.writeByte(effectId); + } } diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/packet/KeepAlive.java b/protocol/src/main/java/net/md_5/bungee/protocol/packet/KeepAlive.java index b004bc416..0c2eb022f 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/packet/KeepAlive.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/packet/KeepAlive.java @@ -1,5 +1,6 @@ package net.md_5.bungee.protocol.packet; +import io.github.waterfallmc.travertine.protocol.MultiVersionPacketV17; import io.netty.buffer.ByteBuf; import lombok.AllArgsConstructor; import lombok.Data; @@ -13,17 +14,33 @@ import net.md_5.bungee.protocol.ProtocolConstants; @NoArgsConstructor @AllArgsConstructor @EqualsAndHashCode(callSuper = false) -public class KeepAlive extends DefinedPacket +public class KeepAlive extends MultiVersionPacketV17 { private long randomId; + // Travertine start + @Override + public void v17Read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) + { + randomId = buf.readInt(); + } + // Travertine end + @Override public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) { randomId = ( protocolVersion >= ProtocolConstants.MINECRAFT_1_12_2 ) ? buf.readLong() : readVarInt( buf ); } + // Travertine start + @Override + public void v17Write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) + { + buf.writeInt((int) randomId); + } + // Travertine end + @Override public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) { diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/packet/LoginSuccess.java b/protocol/src/main/java/net/md_5/bungee/protocol/packet/LoginSuccess.java index 551bd1046..ac8751f6e 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/packet/LoginSuccess.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/packet/LoginSuccess.java @@ -23,6 +23,11 @@ public class LoginSuccess extends DefinedPacket @Override public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) { + // Travertine start + if ( protocolVersion <= ProtocolConstants.MINECRAFT_1_7_2 ) { + uuid = readUndashedUUID( buf ); + } else + // Travertine end if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_16 ) { uuid = readUUID( buf ); @@ -36,6 +41,11 @@ public class LoginSuccess extends DefinedPacket @Override public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) { + // Travertine start + if ( protocolVersion <= ProtocolConstants.MINECRAFT_1_7_2 ) { + writeUndashedUUID( uuid.toString(), buf ); + } else + // Travertine end if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_16 ) { writeUUID( uuid, buf ); @@ -51,4 +61,14 @@ public class LoginSuccess extends DefinedPacket { handler.handle( this ); } + + // Travertine start + private static UUID readUndashedUUID(ByteBuf buf) { + return UUID.fromString( new StringBuilder( readString( buf ) ).insert( 20, '-' ).insert( 16, '-' ).insert( 12, '-' ).insert( 8, '-' ).toString() ); + } + + private static void writeUndashedUUID(String uuid, ByteBuf buf) { + writeString( new StringBuilder( 32 ).append( uuid, 0, 8 ).append( uuid, 9, 13 ).append( uuid, 14, 18 ).append( uuid, 19, 23 ).append( uuid, 24, 36 ).toString(), buf ); + } + // Travertine end } diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/packet/PlayerListItem.java b/protocol/src/main/java/net/md_5/bungee/protocol/packet/PlayerListItem.java index 92bacc7cd..c919f961a 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/packet/PlayerListItem.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/packet/PlayerListItem.java @@ -1,5 +1,7 @@ package net.md_5.bungee.protocol.packet; +import io.github.waterfallmc.travertine.protocol.MultiVersionPacketV17; +import net.md_5.bungee.protocol.DefinedPacket; import io.netty.buffer.ByteBuf; import java.util.UUID; import lombok.Data; @@ -12,12 +14,24 @@ import net.md_5.bungee.protocol.ProtocolConstants; @Data @NoArgsConstructor @EqualsAndHashCode(callSuper = false) -public class PlayerListItem extends DefinedPacket +public class PlayerListItem extends MultiVersionPacketV17 { private Action action; private Item[] items; + // Travertine start + @Override + public void v17Read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) + { + items = new Item[ 1 ]; + Item item = items[ 0 ] = new Item(); + item.displayName = item.username = readString( buf ); + action = !buf.readBoolean() ? Action.REMOVE_PLAYER : Action.ADD_PLAYER; + item.ping = buf.readShort(); + } + // Travertine end + @Override public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) { @@ -72,6 +86,17 @@ public class PlayerListItem extends DefinedPacket } } + // Travertine start + @Override + public void v17Write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) + { + Item item = items[0]; // Only one at a time + writeString( item.displayName, buf ); // TODO: Server unique only! + buf.writeBoolean( action != Action.REMOVE_PLAYER ); + buf.writeShort( item.ping ); + } + // Travertine end + @Override public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) { diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/packet/PluginMessage.java b/protocol/src/main/java/net/md_5/bungee/protocol/packet/PluginMessage.java index 17e12655d..c49c5a567 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/packet/PluginMessage.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/packet/PluginMessage.java @@ -3,6 +3,8 @@ package net.md_5.bungee.protocol.packet; import com.google.common.base.Function; import com.google.common.base.Preconditions; import com.google.common.base.Predicate; +import io.github.waterfallmc.travertine.protocol.MultiVersionPacketV17; +import io.netty.buffer.ByteBufUtil; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; // Waterfall import java.io.ByteArrayInputStream; @@ -21,7 +23,7 @@ import net.md_5.bungee.protocol.ProtocolConstants; @NoArgsConstructor @AllArgsConstructor @EqualsAndHashCode(callSuper = false) -public class PluginMessage extends DefinedPacket +public class PluginMessage extends MultiVersionPacketV17 { public static final Function MODERNISE = new Function() @@ -79,6 +81,15 @@ public class PluginMessage extends DefinedPacket */ private boolean allowExtendedPacket = false; + // Travertine start + @Override + public void v17Read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) + { + tag = readString( buf ); + data = v17readArray( buf ); + } + // Travertine end + @Override public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) { @@ -89,6 +100,15 @@ public class PluginMessage extends DefinedPacket buf.readBytes( data ); } + // Travertine start + @Override + public void v17Write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) + { + writeString( tag, buf ); + v17writeArray( data, buf, allowExtendedPacket ); + } + // Travertine end + @Override public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) { diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/packet/ScoreboardObjective.java b/protocol/src/main/java/net/md_5/bungee/protocol/packet/ScoreboardObjective.java index 3c7905d54..fe290fa3c 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/packet/ScoreboardObjective.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/packet/ScoreboardObjective.java @@ -1,5 +1,6 @@ package net.md_5.bungee.protocol.packet; +import io.github.waterfallmc.travertine.protocol.MultiVersionPacketV17; import io.netty.buffer.ByteBuf; import java.util.Locale; import lombok.AllArgsConstructor; @@ -14,7 +15,7 @@ import net.md_5.bungee.protocol.ProtocolConstants; @NoArgsConstructor @AllArgsConstructor @EqualsAndHashCode(callSuper = false) -public class ScoreboardObjective extends DefinedPacket +public class ScoreboardObjective extends MultiVersionPacketV17 { private String name; @@ -25,6 +26,16 @@ public class ScoreboardObjective extends DefinedPacket */ private byte action; + // Travertine start + @Override + public void v17Read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) + { + name = readString( buf ); + value = readString( buf ); + action = buf.readByte(); + } + // Travertine end + @Override public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) { @@ -43,6 +54,16 @@ public class ScoreboardObjective extends DefinedPacket } } + // Travertine start + @Override + public void v17Write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) + { + writeString( name, buf ); + writeString( value, buf ); + buf.writeByte( action ); + } + // Travertine end + @Override public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) { diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/packet/ScoreboardScore.java b/protocol/src/main/java/net/md_5/bungee/protocol/packet/ScoreboardScore.java index 0b27fc86b..74066702c 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/packet/ScoreboardScore.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/packet/ScoreboardScore.java @@ -1,5 +1,6 @@ package net.md_5.bungee.protocol.packet; +import io.github.waterfallmc.travertine.protocol.MultiVersionPacketV17; import io.netty.buffer.ByteBuf; import lombok.AllArgsConstructor; import lombok.Data; @@ -13,7 +14,7 @@ import net.md_5.bungee.protocol.ProtocolConstants; @NoArgsConstructor @AllArgsConstructor @EqualsAndHashCode(callSuper = false) -public class ScoreboardScore extends DefinedPacket +public class ScoreboardScore extends MultiVersionPacketV17 { private String itemName; @@ -24,6 +25,20 @@ public class ScoreboardScore extends DefinedPacket private String scoreName; private int value; + // Travertine start + @Override + public void v17Read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) + { + itemName = readString( buf ); + action = buf.readByte(); + if ( action != 1 ) + { + scoreName = readString( buf ); + value = buf.readInt(); + } + } + // Travertine end + @Override public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) { @@ -36,6 +51,20 @@ public class ScoreboardScore extends DefinedPacket } } + // Travertine start + @Override + public void v17Write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) + { + writeString( itemName, buf ); + buf.writeByte( action ); + if ( action != 1 ) + { + writeString( scoreName, buf ); + buf.writeInt( value ); + } + } + // Travertine end + @Override public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) { diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/packet/TabCompleteRequest.java b/protocol/src/main/java/net/md_5/bungee/protocol/packet/TabCompleteRequest.java index 3e4ea1928..421805e6e 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/packet/TabCompleteRequest.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/packet/TabCompleteRequest.java @@ -1,5 +1,6 @@ package net.md_5.bungee.protocol.packet; +import io.github.waterfallmc.travertine.protocol.MultiVersionPacketV17; import io.netty.buffer.ByteBuf; import lombok.Data; import lombok.EqualsAndHashCode; @@ -11,7 +12,7 @@ import net.md_5.bungee.protocol.ProtocolConstants; @Data @NoArgsConstructor @EqualsAndHashCode(callSuper = false) -public class TabCompleteRequest extends DefinedPacket +public class TabCompleteRequest extends MultiVersionPacketV17 { private int transactionId; @@ -33,6 +34,13 @@ public class TabCompleteRequest extends DefinedPacket this.hasPositon = hasPosition; this.position = position; } + // Travertine start + @Override + public void v17Read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) + { + cursor = readString( buf ); + } + // Travertine end @Override public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) @@ -57,6 +65,14 @@ public class TabCompleteRequest extends DefinedPacket } } + // Travertine start + @Override + public void v17Write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) + { + writeString( cursor, buf ); + } + // Travertine end + @Override public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) { diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/packet/Team.java b/protocol/src/main/java/net/md_5/bungee/protocol/packet/Team.java index a5555f6af..415a4bcde 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/packet/Team.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/packet/Team.java @@ -1,5 +1,6 @@ package net.md_5.bungee.protocol.packet; +import io.github.waterfallmc.travertine.protocol.MultiVersionPacketV17; import io.netty.buffer.ByteBuf; import lombok.AllArgsConstructor; import lombok.Data; @@ -13,7 +14,7 @@ import net.md_5.bungee.protocol.ProtocolConstants; @NoArgsConstructor @AllArgsConstructor @EqualsAndHashCode(callSuper = false) -public class Team extends DefinedPacket +public class Team extends MultiVersionPacketV17 { private String name; @@ -41,6 +42,31 @@ public class Team extends DefinedPacket this.mode = 1; } + // Travertine start + @Override + public void v17Read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) + { + name = readString( buf ); + mode = buf.readByte(); + if ( mode == 0 || mode == 2 ) + { + displayName = readString( buf ); + prefix = readString( buf ); + suffix = readString( buf ); + friendlyFire = buf.readByte(); + } + if ( mode == 0 || mode == 3 || mode == 4 ) + { + int len = buf.readShort(); + players = new String[ len ]; + for ( int i = 0; i < len; i++ ) + { + players[i] = readString( buf ); + } + } + } + // Travertine end + @Override public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) { @@ -78,6 +104,30 @@ public class Team extends DefinedPacket } } + // Travertine start + @Override + public void v17Write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) + { + writeString( name, buf ); + buf.writeByte( mode ); + if ( mode == 0 || mode == 2 ) + { + writeString( displayName, buf ); + writeString( prefix, buf ); + writeString( suffix, buf ); + buf.writeByte( friendlyFire ); + } + if ( mode == 0 || mode == 3 || mode == 4 ) + { + buf.writeShort( players.length ); + for ( String player : players ) + { + writeString( player, buf ); + } + } + } + // Travertine end + @Override public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) { diff --git a/proxy/src/main/java/net/md_5/bungee/BungeeCord.java b/proxy/src/main/java/net/md_5/bungee/BungeeCord.java index f7f1e7ccd..a17ed68ec 100644 --- a/proxy/src/main/java/net/md_5/bungee/BungeeCord.java +++ b/proxy/src/main/java/net/md_5/bungee/BungeeCord.java @@ -170,6 +170,14 @@ public class BungeeCord extends ProxyServer .registerTypeAdapter( SelectorComponent.class, new SelectorComponentSerializer() ) .registerTypeAdapter( ServerPing.PlayerInfo.class, new PlayerInfoSerializer() ) .registerTypeAdapter( Favicon.class, Favicon.getFaviconTypeAdapter() ).create(); + // Travertine start + public final Gson gsonLegacy = new GsonBuilder() + .registerTypeAdapter( BaseComponent.class, new ComponentSerializer() ) + .registerTypeAdapter( TextComponent.class, new TextComponentSerializer() ) + .registerTypeAdapter( TranslatableComponent.class, new TranslatableComponentSerializer() ) + .registerTypeAdapter( ServerPing.PlayerInfo.class, new PlayerInfoSerializer( ProtocolConstants.MINECRAFT_1_7_2 ) ) + .registerTypeAdapter( Favicon.class, Favicon.getFaviconTypeAdapter() ).create(); + // Travertine end @Getter private ConnectionThrottle connectionThrottle; private final ModuleManager moduleManager = new ModuleManager(); diff --git a/proxy/src/main/java/net/md_5/bungee/BungeeTitle.java b/proxy/src/main/java/net/md_5/bungee/BungeeTitle.java index 494213db8..1d89acf5b 100644 --- a/proxy/src/main/java/net/md_5/bungee/BungeeTitle.java +++ b/proxy/src/main/java/net/md_5/bungee/BungeeTitle.java @@ -5,6 +5,7 @@ import net.md_5.bungee.api.chat.BaseComponent; import net.md_5.bungee.api.connection.ProxiedPlayer; import net.md_5.bungee.chat.ComponentSerializer; import net.md_5.bungee.protocol.DefinedPacket; +import net.md_5.bungee.protocol.ProtocolConstants; import net.md_5.bungee.protocol.packet.Title.Action; public class BungeeTitle implements Title @@ -151,6 +152,7 @@ public class BungeeTitle implements Title @Override public Title send(ProxiedPlayer player) { + if ( ProtocolConstants.isBeforeOrEq( player.getPendingConnection().getVersion(), ProtocolConstants.MINECRAFT_1_7_6 ) ) return this; sendPacket( player, clear ); sendPacket( player, reset ); sendPacket( player, times ); diff --git a/proxy/src/main/java/net/md_5/bungee/PlayerInfoSerializer.java b/proxy/src/main/java/net/md_5/bungee/PlayerInfoSerializer.java index 491cf1a16..299a216cd 100644 --- a/proxy/src/main/java/net/md_5/bungee/PlayerInfoSerializer.java +++ b/proxy/src/main/java/net/md_5/bungee/PlayerInfoSerializer.java @@ -10,17 +10,32 @@ import com.google.gson.JsonSerializer; import java.lang.reflect.Type; import java.util.UUID; import net.md_5.bungee.api.ServerPing; +import net.md_5.bungee.protocol.ProtocolConstants; public class PlayerInfoSerializer implements JsonSerializer, JsonDeserializer { + // Travertine start + private final int protocol; + + public PlayerInfoSerializer() + { + this.protocol = ProtocolConstants.MINECRAFT_1_7_6; + } + + public PlayerInfoSerializer(int protocol) + { + this.protocol = protocol; + } + // Travertine end + @Override public ServerPing.PlayerInfo deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { JsonObject js = json.getAsJsonObject(); ServerPing.PlayerInfo info = new ServerPing.PlayerInfo( js.get( "name" ).getAsString(), (UUID) null ); String id = js.get( "id" ).getAsString(); - if ( !id.contains( "-" ) ) + if ( ProtocolConstants.isBeforeOrEq( protocol, ProtocolConstants.MINECRAFT_1_7_2 ) || !id.contains( "-" ) ) // Travertine { info.setId( id ); } else @@ -35,7 +50,15 @@ public class PlayerInfoSerializer implements JsonSerializer= ProtocolConstants.MINECRAFT_1_13 ? "minecraft:brand" : "MC|Brand", brand, handshakeHandler.isServerForge() ) ); - brand.release(); + // Travertine start + String brandString = bungee.getName() + " (" + bungee.getVersion() + ")"; + + if ( ProtocolConstants.isBeforeOrEq( user.getPendingConnection().getVersion(), ProtocolConstants.MINECRAFT_1_7_6 ) ) + { + user.unsafe().sendPacket( new PluginMessage( "MC|Brand", brandString.getBytes( StandardCharsets.UTF_8 ), handshakeHandler.isServerForge() ) ); + } else + { + ByteBuf brand = ByteBufAllocator.DEFAULT.heapBuffer(); + DefinedPacket.writeString(brandString, brand); + user.unsafe().sendPacket( new PluginMessage( user.getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_13 ? "minecraft:brand" : "MC|Brand", brand, handshakeHandler.isServerForge() ) ); + brand.release(); + } + // Travertine end } user.setDimension( login.getDimension() ); @@ -286,7 +297,7 @@ public class ServerConnector extends PacketHandler if ( !user.isDisableEntityMetadataRewrite() ) { // Waterfall for ( Objective objective : serverScoreboard.getObjectives() ) { - user.unsafe().sendPacket( new ScoreboardObjective( objective.getName(), objective.getValue(), ScoreboardObjective.HealthDisplay.fromString( objective.getType() ), (byte) 1 ) ); + user.unsafe().sendPacket( new ScoreboardObjective( objective.getName(), objective.getValue(), objective.getType() == null ? null : ScoreboardObjective.HealthDisplay.fromString(objective.getType()), (byte) 1 ) ); // Travertine - 1.7 } for ( Score score : serverScoreboard.getScores() ) { @@ -456,6 +467,14 @@ public class ServerConnector extends PacketHandler { this.handshakeHandler.handle( pluginMessage ); + // Travertine start + if ( user.getForgeClientHandler().checkUserOutdated() ) + { + ch.close(); + user.getPendingConnects().remove(target); + } + // Travertine end + // We send the message as part of the handler, so don't send it here. throw CancelSendSignal.INSTANCE; } diff --git a/proxy/src/main/java/net/md_5/bungee/UserConnection.java b/proxy/src/main/java/net/md_5/bungee/UserConnection.java index 7ec119ea0..986a9d052 100644 --- a/proxy/src/main/java/net/md_5/bungee/UserConnection.java +++ b/proxy/src/main/java/net/md_5/bungee/UserConnection.java @@ -193,6 +193,7 @@ public final class UserConnection implements ProxiedPlayer public void setDisplayName(String name) { Preconditions.checkNotNull( name, "displayName" ); + Preconditions.checkArgument( name.length() <= 16, "Display name cannot be longer than 16 characters" ); // Travertine displayName = name; } @@ -497,7 +498,8 @@ public final class UserConnection implements ProxiedPlayer // transform score components message = ChatComponentTransformer.getInstance().transform( this, true, message ); - if ( position == ChatMessageType.ACTION_BAR ) + // Action bar doesn't display the new JSON formattings, legacy works - send it using this for now + if ( position == ChatMessageType.ACTION_BAR && getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_8 ) // Travertine { // Versions older than 1.11 cannot send the Action bar with the new JSON formattings // Fix by converting to a legacy message, see https://bugs.mojang.com/browse/MC-119145 @@ -693,6 +695,7 @@ public final class UserConnection implements ProxiedPlayer @Override public void setTabHeader(BaseComponent header, BaseComponent footer) { + if ( ProtocolConstants.isBeforeOrEq( pendingConnection.getVersion(), ProtocolConstants.MINECRAFT_1_7_6 ) ) return; // Travertine header = ChatComponentTransformer.getInstance().transform( this, true, header )[0]; footer = ChatComponentTransformer.getInstance().transform( this, true, footer )[0]; @@ -705,6 +708,7 @@ public final class UserConnection implements ProxiedPlayer @Override public void setTabHeader(BaseComponent[] header, BaseComponent[] footer) { + if ( ProtocolConstants.isBeforeOrEq( pendingConnection.getVersion(), ProtocolConstants.MINECRAFT_1_7_6 ) ) return; // Travertine header = ChatComponentTransformer.getInstance().transform( this, true, header ); footer = ChatComponentTransformer.getInstance().transform( this, true, footer ); @@ -734,6 +738,7 @@ public final class UserConnection implements ProxiedPlayer public void setCompressionThreshold(int compressionThreshold) { + if ( ProtocolConstants.isBeforeOrEq( pendingConnection.getVersion(), ProtocolConstants.MINECRAFT_1_7_6 ) ) return; // Travertine if ( !ch.isClosing() && this.compressionThreshold == -1 && compressionThreshold >= 0 ) { this.compressionThreshold = compressionThreshold; diff --git a/proxy/src/main/java/net/md_5/bungee/connection/DownstreamBridge.java b/proxy/src/main/java/net/md_5/bungee/connection/DownstreamBridge.java index 9e180c30c..d54d8539b 100644 --- a/proxy/src/main/java/net/md_5/bungee/connection/DownstreamBridge.java +++ b/proxy/src/main/java/net/md_5/bungee/connection/DownstreamBridge.java @@ -20,6 +20,7 @@ import io.netty.buffer.Unpooled; import io.netty.channel.unix.DomainSocketAddress; import java.io.DataInput; import java.net.InetSocketAddress; +import java.nio.charset.StandardCharsets; // Waterfall import java.util.ArrayList; import java.util.HashMap; // Waterfall import java.util.List; @@ -179,7 +180,7 @@ public class DownstreamBridge extends PacketHandler switch ( objective.getAction() ) { case 0: - serverScoreboard.addObjective( new Objective( objective.getName(), objective.getValue(), objective.getType().toString() ) ); + serverScoreboard.addObjective( new Objective( objective.getName(), objective.getValue(), objective.getType() != null ? objective.getType().toString() : null) ); // Travertine - 1.7 protocol support break; case 1: serverScoreboard.removeObjective( objective.getName() ); @@ -189,7 +190,7 @@ public class DownstreamBridge extends PacketHandler if ( oldObjective != null ) { oldObjective.setValue( objective.getValue() ); - oldObjective.setType( objective.getType().toString() ); + oldObjective.setType( objective.getType() != null ? objective.getType().toString() : null ); // Travertine - 1.7 protocol support } break; default: @@ -286,16 +287,28 @@ public class DownstreamBridge extends PacketHandler if ( pluginMessage.getTag().equals( con.getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_13 ? "minecraft:brand" : "MC|Brand" ) ) { - ByteBuf brand = Unpooled.wrappedBuffer( pluginMessage.getData() ); - String serverBrand = DefinedPacket.readString( brand ); - brand.release(); - - Preconditions.checkState( !serverBrand.contains( bungee.getName() ), "Cannot connect proxy to itself!" ); - - brand = ByteBufAllocator.DEFAULT.heapBuffer(); - DefinedPacket.writeString( bungee.getName() + " <- " + serverBrand, brand ); // Waterfall - pluginMessage.setData( brand ); - brand.release(); + // Travertine start + if ( ProtocolConstants.isAfterOrEq( con.getPendingConnection().getVersion(), ProtocolConstants.MINECRAFT_1_8 ) ) + { + try + { + ByteBuf brand = Unpooled.wrappedBuffer(pluginMessage.getData()); + String serverBrand = DefinedPacket.readString(brand); + brand.release(); + brand = ByteBufAllocator.DEFAULT.heapBuffer(); + DefinedPacket.writeString(bungee.getName() + " <- " + serverBrand, brand ); // Waterfall + pluginMessage.setData(brand); + brand.release(); + } catch (Exception ProtocolHacksSuck) + { + return; + } + } else + { + String serverBrand = new String( pluginMessage.getData(), StandardCharsets.UTF_8); + pluginMessage.setData( ( bungee.getName() + " <- " + serverBrand ).getBytes(StandardCharsets.UTF_8) ); // Travertine + } + // Travertine end // changes in the packet are ignored so we need to send it manually con.unsafe().sendPacket( pluginMessage ); throw CancelSendSignal.INSTANCE; diff --git a/proxy/src/main/java/net/md_5/bungee/connection/InitialHandler.java b/proxy/src/main/java/net/md_5/bungee/connection/InitialHandler.java index b7ecd828e..3b82219d1 100644 --- a/proxy/src/main/java/net/md_5/bungee/connection/InitialHandler.java +++ b/proxy/src/main/java/net/md_5/bungee/connection/InitialHandler.java @@ -3,6 +3,8 @@ package net.md_5.bungee.connection; import com.google.common.base.Charsets; import com.google.common.base.Preconditions; import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; import java.math.BigInteger; import java.net.InetSocketAddress; import java.net.SocketAddress; @@ -257,12 +259,28 @@ public class InitialHandler extends PacketHandler implements PendingConnection @Override public void done(ProxyPingEvent pingResult, Throwable error) { - Gson gson = BungeeCord.getInstance().gson; - unsafe.sendPacket( new StatusResponse( gson.toJson( pingResult.getResponse() ) ) ); + Gson gson = handshake.getProtocolVersion() == ProtocolConstants.MINECRAFT_1_7_2 ? BungeeCord.getInstance().gsonLegacy : BungeeCord.getInstance().gson; // Travertine if ( bungee.getConnectionThrottle() != null ) { bungee.getConnectionThrottle().unthrottle( getSocketAddress() ); } + // Travertine start + if ( ProtocolConstants.isBeforeOrEq( handshake.getProtocolVersion() , ProtocolConstants.MINECRAFT_1_8 ) ) + { + // Minecraft < 1.9 doesn't send string server descriptions as chat components. Older 1.7 + // clients even crash when encountering a chat component instead of a string. To be on the + // safe side, always send legacy descriptions for < 1.9 clients. + JsonElement element = gson.toJsonTree(pingResult.getResponse()); + Preconditions.checkArgument(element.isJsonObject(), "Response is not a JSON object"); + JsonObject object = element.getAsJsonObject(); + object.addProperty("description", pingResult.getResponse().getDescription()); + + unsafe.sendPacket(new StatusResponse(gson.toJson(element))); + } else + { + unsafe.sendPacket( new StatusResponse( gson.toJson( pingResult.getResponse() ) ) ); + } + // Travertine end } }; diff --git a/proxy/src/main/java/net/md_5/bungee/connection/PingHandler.java b/proxy/src/main/java/net/md_5/bungee/connection/PingHandler.java index 6df3f3dd9..6cd71071e 100644 --- a/proxy/src/main/java/net/md_5/bungee/connection/PingHandler.java +++ b/proxy/src/main/java/net/md_5/bungee/connection/PingHandler.java @@ -16,6 +16,7 @@ import net.md_5.bungee.protocol.MinecraftDecoder; import net.md_5.bungee.protocol.MinecraftEncoder; import net.md_5.bungee.protocol.PacketWrapper; import net.md_5.bungee.protocol.Protocol; +import net.md_5.bungee.protocol.ProtocolConstants; import net.md_5.bungee.protocol.packet.Handshake; import net.md_5.bungee.protocol.packet.StatusRequest; import net.md_5.bungee.protocol.packet.StatusResponse; @@ -65,7 +66,7 @@ public class PingHandler extends PacketHandler @SuppressFBWarnings("UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR") public void handle(StatusResponse statusResponse) throws Exception { - Gson gson = BungeeCord.getInstance().gson; + Gson gson = protocol == ProtocolConstants.MINECRAFT_1_7_2 ? BungeeCord.getInstance().gsonLegacy : BungeeCord.getInstance().gson; // Travertine ServerPing serverPing = gson.fromJson( statusResponse.getResponse(), ServerPing.class ); ( (BungeeServerInfo) target ).cachePing( serverPing ); callback.done( serverPing, null ); diff --git a/proxy/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java b/proxy/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java index 4d7b1b23e..ad3bdee56 100644 --- a/proxy/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java +++ b/proxy/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java @@ -85,7 +85,12 @@ public class UpstreamBridge extends PacketHandler } ); for ( ProxiedPlayer player : con.getServer().getInfo().getPlayers() ) { - player.unsafe().sendPacket( packet ); + // Travertine start + if ( ProtocolConstants.isAfterOrEq( player.getPendingConnection().getVersion(), ProtocolConstants.MINECRAFT_1_8 ) ) + { + player.unsafe().sendPacket( packet ); + } + // Travertine end } con.getServer().disconnect( "Quitting" ); } diff --git a/proxy/src/main/java/net/md_5/bungee/entitymap/EntityMap.java b/proxy/src/main/java/net/md_5/bungee/entitymap/EntityMap.java index db93d8835..a3a12e19b 100644 --- a/proxy/src/main/java/net/md_5/bungee/entitymap/EntityMap.java +++ b/proxy/src/main/java/net/md_5/bungee/entitymap/EntityMap.java @@ -35,6 +35,10 @@ public abstract class EntityMap // Waterfall end switch ( version ) { + case ProtocolConstants.MINECRAFT_1_7_2: + return EntityMap_1_7_2.INSTANCE; + case ProtocolConstants.MINECRAFT_1_7_6: + return EntityMap_1_7_6.INSTANCE; case ProtocolConstants.MINECRAFT_1_8: return EntityMap_1_8.INSTANCE; case ProtocolConstants.MINECRAFT_1_9: diff --git a/proxy/src/main/java/net/md_5/bungee/entitymap/EntityMap_1_7_2.java b/proxy/src/main/java/net/md_5/bungee/entitymap/EntityMap_1_7_2.java new file mode 100644 index 000000000..65c1a9ec8 --- /dev/null +++ b/proxy/src/main/java/net/md_5/bungee/entitymap/EntityMap_1_7_2.java @@ -0,0 +1,102 @@ +// Travertine start +package net.md_5.bungee.entitymap; + +import io.netty.buffer.ByteBuf; +import net.md_5.bungee.protocol.DefinedPacket; +import net.md_5.bungee.protocol.ProtocolConstants; + +class EntityMap_1_7_2 extends EntityMap +{ + + static final EntityMap INSTANCE = new EntityMap_1_7_2(); + + EntityMap_1_7_2() + { + addRewrite( 0x04, ProtocolConstants.Direction.TO_CLIENT, false ); // Entity Equipment + addRewrite( 0x0A, ProtocolConstants.Direction.TO_CLIENT, false ); // Use bed + addRewrite( 0x0B, ProtocolConstants.Direction.TO_CLIENT, true ); // Animation + addRewrite( 0x0C, ProtocolConstants.Direction.TO_CLIENT, true ); // Spawn Player + addRewrite( 0x0D, ProtocolConstants.Direction.TO_CLIENT, false ); // Collect Item + addRewrite( 0x0E, ProtocolConstants.Direction.TO_CLIENT, true ); // Spawn Object + addRewrite( 0x0F, ProtocolConstants.Direction.TO_CLIENT, true ); // Spawn Mob + addRewrite( 0x10, ProtocolConstants.Direction.TO_CLIENT, true ); // Spawn Painting + addRewrite( 0x11, ProtocolConstants.Direction.TO_CLIENT, true ); // Spawn Experience Orb + addRewrite( 0x12, ProtocolConstants.Direction.TO_CLIENT, false ); // Entity Velocity + addRewrite( 0x14, ProtocolConstants.Direction.TO_CLIENT, false ); // Entity + addRewrite( 0x15, ProtocolConstants.Direction.TO_CLIENT, false ); // Entity Relative Move + addRewrite( 0x16, ProtocolConstants.Direction.TO_CLIENT, false ); // Entity Look + addRewrite( 0x17, ProtocolConstants.Direction.TO_CLIENT, false ); // Entity Look and Relative Move + addRewrite( 0x18, ProtocolConstants.Direction.TO_CLIENT, false ); // Entity Teleport + addRewrite( 0x19, ProtocolConstants.Direction.TO_CLIENT, false ); // Entity Head Look + addRewrite( 0x1A, ProtocolConstants.Direction.TO_CLIENT, false ); // Entity Status + addRewrite( 0x1B, ProtocolConstants.Direction.TO_CLIENT, false ); // Attach Entity + addRewrite( 0x1C, ProtocolConstants.Direction.TO_CLIENT, false ); // Entity Metadata + addRewrite( 0x1D, ProtocolConstants.Direction.TO_CLIENT, false ); // Entity Effect + addRewrite( 0x1E, ProtocolConstants.Direction.TO_CLIENT, false ); // Remove Entity Effect + addRewrite( 0x20, ProtocolConstants.Direction.TO_CLIENT, false ); // Entity Properties + addRewrite( 0x25, ProtocolConstants.Direction.TO_CLIENT, true ); // Block Break Animation + addRewrite( 0x2C, ProtocolConstants.Direction.TO_CLIENT, true ); // Spawn Global Entity + + addRewrite( 0x02, ProtocolConstants.Direction.TO_SERVER, false ); // Use Entity + addRewrite( 0x0A, ProtocolConstants.Direction.TO_SERVER, false ); // Animation + addRewrite( 0x0B, ProtocolConstants.Direction.TO_SERVER, false ); // Entity Action + } + + @Override + public void rewriteClientbound(ByteBuf packet, int oldId, int newId) + { + super.rewriteClientbound( packet, oldId, newId ); + + //Special cases + int readerIndex = packet.readerIndex(); + int packetId = DefinedPacket.readVarInt( packet ); + int packetIdLength = packet.readerIndex() - readerIndex; + if ( packetId == 0x0D /* Collect Item */ || packetId == 0x1B /* Attach Entity */ ) + { + rewriteInt( packet, oldId, newId, readerIndex + packetIdLength + 4 ); + } else if ( packetId == 0x13 /* Destroy Entities */ ) + { + int count = packet.getByte( packetIdLength ); + for ( int i = 0; i < count; i++ ) + { + rewriteInt( packet, oldId, newId, packetIdLength + 1 + i * 4 ); + } + } else if ( packetId == 0x0E /* Spawn Object */ ) + { + DefinedPacket.readVarInt( packet ); + int type = packet.readUnsignedByte(); + + if ( type == 60 || type == 90 ) + { + packet.skipBytes( 14 ); + int position = packet.readerIndex(); + int readId = packet.readInt(); + int changedId = -1; + if ( readId == oldId ) + { + packet.setInt( position, newId ); + changedId = newId; + } else if ( readId == newId ) + { + packet.setInt( position, oldId ); + changedId = oldId; + } + if ( changedId != -1 ) + { + if ( changedId == 0 && readId != 0 ) + { // Trim off the extra data + packet.readerIndex( readerIndex ); + packet.writerIndex( packet.readableBytes() - 6 ); + } else if ( changedId != 0 && readId == 0 ) + { // Add on the extra data + packet.readerIndex( readerIndex ); + packet.capacity( packet.readableBytes() + 6 ); + packet.writerIndex( packet.readableBytes() + 6 ); + } + } + } + } + packet.readerIndex( readerIndex ); + } +} +// Travertine end diff --git a/proxy/src/main/java/net/md_5/bungee/entitymap/EntityMap_1_7_6.java b/proxy/src/main/java/net/md_5/bungee/entitymap/EntityMap_1_7_6.java new file mode 100644 index 000000000..6755fe845 --- /dev/null +++ b/proxy/src/main/java/net/md_5/bungee/entitymap/EntityMap_1_7_6.java @@ -0,0 +1,62 @@ +// Travertine start +package net.md_5.bungee.entitymap; + +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import io.netty.buffer.ByteBuf; +import net.md_5.bungee.BungeeCord; +import net.md_5.bungee.UserConnection; +import net.md_5.bungee.connection.LoginResult; +import net.md_5.bungee.protocol.DefinedPacket; + +class EntityMap_1_7_6 extends EntityMap_1_7_2 +{ + + static final EntityMap_1_7_6 INSTANCE = new EntityMap_1_7_6(); + + @Override + @SuppressFBWarnings("DLS_DEAD_LOCAL_STORE") + public void rewriteClientbound(ByteBuf packet, int oldId, int newId) + { + super.rewriteClientbound( packet, oldId, newId ); + + int readerIndex = packet.readerIndex(); + int packetId = DefinedPacket.readVarInt( packet ); + int packetIdLength = packet.readerIndex() - readerIndex; + if ( packetId == 0x0C /* Spawn Player */ ) + { + DefinedPacket.readVarInt( packet ); + int idLength = packet.readerIndex() - readerIndex - packetIdLength; + String uuid = DefinedPacket.readString( packet ); + String username = DefinedPacket.readString( packet ); + int props = DefinedPacket.readVarInt( packet ); + if ( props == 0 ) + { + UserConnection player = (UserConnection) BungeeCord.getInstance().getPlayer( username ); + if ( player != null ) + { + LoginResult profile = player.getPendingConnection().getLoginProfile(); + if ( profile != null && profile.getProperties() != null + && profile.getProperties().length >= 1 ) + { + ByteBuf rest = packet.copy(); + packet.readerIndex( readerIndex ); + packet.writerIndex( readerIndex + packetIdLength + idLength ); + DefinedPacket.writeString( player.getUniqueId().toString(), packet ); + DefinedPacket.writeString( username, packet ); + DefinedPacket.writeVarInt( profile.getProperties().length, packet ); + for ( LoginResult.Property property : profile.getProperties() ) + { + DefinedPacket.writeString( property.getName(), packet ); + DefinedPacket.writeString( property.getValue(), packet ); + DefinedPacket.writeString( property.getSignature(), packet ); + } + packet.writeBytes( rest ); + rest.release(); + } + } + } + } + packet.readerIndex( readerIndex ); + } +} +// Travertine end diff --git a/proxy/src/main/java/net/md_5/bungee/forge/ForgeClientHandler.java b/proxy/src/main/java/net/md_5/bungee/forge/ForgeClientHandler.java index bea2bbff9..f61de1278 100644 --- a/proxy/src/main/java/net/md_5/bungee/forge/ForgeClientHandler.java +++ b/proxy/src/main/java/net/md_5/bungee/forge/ForgeClientHandler.java @@ -8,6 +8,7 @@ import lombok.Getter; import lombok.NonNull; import lombok.RequiredArgsConstructor; import lombok.Setter; +import net.md_5.bungee.BungeeCord; import net.md_5.bungee.UserConnection; import net.md_5.bungee.protocol.ProtocolConstants; import net.md_5.bungee.protocol.packet.EntityRemoveEffect; @@ -23,6 +24,12 @@ public class ForgeClientHandler @NonNull private final UserConnection con; + // Travertine start + @Getter + @Setter(AccessLevel.PACKAGE) + private boolean forgeOutdated = false; + // Travertine end + /** * The users' mod list. */ @@ -175,4 +182,22 @@ public class ForgeClientHandler { return fmlTokenInHandshake || clientModList != null; } + + // Travertine start + /** + * Checks to see if a user is using an outdated FML build, and takes + * appropriate action on the User side. This should only be called during a + * server connection, by the ServerConnector + * + * @return true if the user's FML build is outdated, otherwise + * false + */ + public boolean checkUserOutdated() { + if (forgeOutdated) { + con.disconnect( BungeeCord.getInstance().getTranslation("connect_kick_outdated_forge") ); + } + return forgeOutdated; + } + // Travertine end + } diff --git a/proxy/src/main/java/net/md_5/bungee/forge/ForgeClientHandshakeState.java b/proxy/src/main/java/net/md_5/bungee/forge/ForgeClientHandshakeState.java index 5e02f8c8a..e3c1b9b95 100644 --- a/proxy/src/main/java/net/md_5/bungee/forge/ForgeClientHandshakeState.java +++ b/proxy/src/main/java/net/md_5/bungee/forge/ForgeClientHandshakeState.java @@ -3,6 +3,7 @@ package net.md_5.bungee.forge; import java.util.Map; import net.md_5.bungee.ServerConnector; import net.md_5.bungee.UserConnection; +import net.md_5.bungee.protocol.ProtocolConstants; import net.md_5.bungee.protocol.packet.PluginMessage; /** @@ -84,6 +85,22 @@ enum ForgeClientHandshakeState implements IForgeClientPacketHandler clientModList = ForgeUtils.readModList( message ); con.getForgeClientHandler().setClientModList( clientModList ); + // Travertine start + // If the user is below 1.8, we need to check the version of FML - it's not always an OK version. + if ( ProtocolConstants.isBeforeOrEq( con.getPendingConnection().getVersion(), ProtocolConstants.MINECRAFT_1_7_6 ) ) + { + // Get the version from the mod list. + int buildNumber = ForgeUtils.getFmlBuildNumber( clientModList ); + + // If we get 0, we're probably using a testing build, so let it though. Otherwise, check the build number. + if ( buildNumber < ForgeConstants.FML_MIN_BUILD_VERSION && buildNumber != 0 ) + { + // Mark the user as an old Forge user. This will then cause any Forge ServerConnectors to cancel any + // connections to it. + con.getForgeClientHandler().setForgeOutdated( true ); + } + } + // Travertine end } return WAITINGSERVERDATA; diff --git a/proxy/src/main/java/net/md_5/bungee/tab/ServerUnique.java b/proxy/src/main/java/net/md_5/bungee/tab/ServerUnique.java index daf12f74e..e33861abb 100644 --- a/proxy/src/main/java/net/md_5/bungee/tab/ServerUnique.java +++ b/proxy/src/main/java/net/md_5/bungee/tab/ServerUnique.java @@ -4,12 +4,14 @@ import java.util.Collection; import java.util.HashSet; import java.util.UUID; import net.md_5.bungee.api.connection.ProxiedPlayer; +import net.md_5.bungee.protocol.ProtocolConstants; import net.md_5.bungee.protocol.packet.PlayerListItem; public class ServerUnique extends TabList { private final Collection uuids = new HashSet<>(); + private final Collection usernames = new HashSet<>(); // Travertine - Support for <=1.7.9 public ServerUnique(ProxiedPlayer player) { @@ -23,10 +25,26 @@ public class ServerUnique extends TabList { if ( playerListItem.getAction() == PlayerListItem.Action.ADD_PLAYER ) { - uuids.add( item.getUuid() ); + // Travertine start + if ( item.getUuid() != null ) + { + uuids.add( item.getUuid() ); + } else + { + usernames.add( item.getUsername() ); + } + // Travertine end } else if ( playerListItem.getAction() == PlayerListItem.Action.REMOVE_PLAYER ) { - uuids.remove( item.getUuid() ); + // Travertine start + if ( item.getUuid() != null ) + { + uuids.remove( item.getUuid() ); + } else + { + usernames.remove( item.getUsername() ); + } + // Travertine end } } player.unsafe().sendPacket( playerListItem ); @@ -43,16 +61,44 @@ public class ServerUnique extends TabList { PlayerListItem packet = new PlayerListItem(); packet.setAction( PlayerListItem.Action.REMOVE_PLAYER ); - PlayerListItem.Item[] items = new PlayerListItem.Item[ uuids.size() ]; + PlayerListItem.Item[] items = new PlayerListItem.Item[ uuids.size() + usernames.size() ]; // Travertine int i = 0; for ( UUID uuid : uuids ) { PlayerListItem.Item item = items[i++] = new PlayerListItem.Item(); item.setUuid( uuid ); } + // Travertine start + for ( String username : usernames ) + { + PlayerListItem.Item item = items[i++] = new PlayerListItem.Item(); + item.setUsername( username ); + item.setDisplayName( username ); + } + // Travertine end packet.setItems( items ); - player.unsafe().sendPacket( packet ); + // Travertine start + if ( ProtocolConstants.isAfterOrEq( player.getPendingConnection().getVersion(), ProtocolConstants.MINECRAFT_1_8 ) ) + { + player.unsafe().sendPacket( packet ); + } else + { + // Split up the packet + for ( PlayerListItem.Item item : packet.getItems() ) + { + PlayerListItem p2 = new PlayerListItem(); + p2.setAction( packet.getAction() ); + + p2.setItems( new PlayerListItem.Item[] + { + item + } ); + player.unsafe().sendPacket( p2 ); + } + } + // Travertine end uuids.clear(); + usernames.clear(); // Travertine } @Override -- 2.31.1