Implement dual protocol version support.
This commit is contained in:
		| @@ -174,6 +174,7 @@ public abstract class ProxyServer | ||||
|      * | ||||
|      * @return the supported Minecraft version | ||||
|      */ | ||||
|     @Deprecated | ||||
|     public abstract String getGameVersion(); | ||||
|  | ||||
|     /** | ||||
| @@ -181,6 +182,7 @@ public abstract class ProxyServer | ||||
|      * | ||||
|      * @return the Minecraft protocol version | ||||
|      */ | ||||
|     @Deprecated | ||||
|     public abstract int getProtocolVersion(); | ||||
|  | ||||
|     /** | ||||
|   | ||||
| @@ -114,9 +114,25 @@ public abstract class DefinedPacket | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public abstract void read(ByteBuf buf); | ||||
|     public void read(ByteBuf buf) | ||||
|     { | ||||
|         throw new UnsupportedOperationException( "Packet must implement read method" ); | ||||
|     } | ||||
|  | ||||
|     public abstract void write(ByteBuf buf); | ||||
|     public void read(ByteBuf buf, Protocol.ProtocolDirection direction, int protocolVersion) | ||||
|     { | ||||
|         read( buf ); | ||||
|     } | ||||
|  | ||||
|     public void write(ByteBuf buf) | ||||
|     { | ||||
|         throw new UnsupportedOperationException( "Packet must implement write method" ); | ||||
|     } | ||||
|  | ||||
|     public void write(ByteBuf buf, Protocol.ProtocolDirection direction, int protocolVersion) | ||||
|     { | ||||
|         write( buf ); | ||||
|     } | ||||
|  | ||||
|     public abstract void handle(AbstractPacketHandler handler) throws Exception; | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,5 @@ | ||||
| package net.md_5.bungee.protocol; | ||||
|  | ||||
| import com.google.common.base.Charsets; | ||||
| import io.netty.buffer.ByteBuf; | ||||
| import io.netty.channel.ChannelHandlerContext; | ||||
| import io.netty.handler.codec.ByteToMessageDecoder; | ||||
| @@ -15,6 +14,8 @@ public class MinecraftDecoder extends ByteToMessageDecoder | ||||
|     @Setter | ||||
|     private Protocol protocol; | ||||
|     private boolean server; | ||||
|     @Setter | ||||
|     private int protocolVersion; | ||||
|  | ||||
|     @Override | ||||
|     protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception | ||||
| @@ -28,7 +29,7 @@ public class MinecraftDecoder extends ByteToMessageDecoder | ||||
|         if ( prot.hasPacket( packetId ) ) | ||||
|         { | ||||
|             packet = prot.createPacket( packetId ); | ||||
|             packet.read( in ); | ||||
|             packet.read( in, prot, protocolVersion ); | ||||
|             if ( in.readableBytes() != 0 ) | ||||
|             { | ||||
|                 throw new BadPacketException( "Did not read all bytes from packet " + packet.getClass() + " " + packetId + " Protocol " + protocol + " Direction " + prot ); | ||||
|   | ||||
| @@ -13,12 +13,14 @@ public class MinecraftEncoder extends MessageToByteEncoder<DefinedPacket> | ||||
|     @Setter | ||||
|     private Protocol protocol; | ||||
|     private boolean server; | ||||
|     @Setter | ||||
|     private int protocolVersion; | ||||
|  | ||||
|     @Override | ||||
|     protected void encode(ChannelHandlerContext ctx, DefinedPacket msg, ByteBuf out) throws Exception | ||||
|     { | ||||
|         Protocol.ProtocolDirection prot = ( server ) ? protocol.TO_CLIENT : protocol.TO_SERVER; | ||||
|         DefinedPacket.writeVarInt( prot.getId( msg.getClass() ), out ); | ||||
|         msg.write( out ); | ||||
|         msg.write( out, prot, protocolVersion ); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -4,6 +4,8 @@ import com.google.common.base.Preconditions; | ||||
| import gnu.trove.map.TObjectIntMap; | ||||
| import gnu.trove.map.hash.TObjectIntHashMap; | ||||
| import java.lang.reflect.Constructor; | ||||
| import java.util.Arrays; | ||||
| import java.util.List; | ||||
| import lombok.RequiredArgsConstructor; | ||||
| import net.md_5.bungee.protocol.packet.Chat; | ||||
| import net.md_5.bungee.protocol.packet.ClientSettings; | ||||
| @@ -95,8 +97,7 @@ public enum Protocol | ||||
|             }; | ||||
|     /*========================================================================*/ | ||||
|     public static final int MAX_PACKET_ID = 0xFF; | ||||
|     public static final int PROTOCOL_VERSION = 0x04; | ||||
|     public static final String MINECRAFT_VERSION = "1.7.2"; | ||||
|     public static List<Integer> supportedVersions = Arrays.asList( 4, 8 ); | ||||
|     /*========================================================================*/ | ||||
|     public final ProtocolDirection TO_SERVER = new ProtocolDirection( "TO_SERVER" ); | ||||
|     public final ProtocolDirection TO_CLIENT = new ProtocolDirection( "TO_CLIENT" ); | ||||
|   | ||||
| @@ -7,6 +7,7 @@ import lombok.Data; | ||||
| import lombok.EqualsAndHashCode; | ||||
| import lombok.NoArgsConstructor; | ||||
| import net.md_5.bungee.protocol.AbstractPacketHandler; | ||||
| import net.md_5.bungee.protocol.Protocol; | ||||
|  | ||||
| @Data | ||||
| @NoArgsConstructor | ||||
| @@ -16,17 +17,31 @@ public class Chat extends DefinedPacket | ||||
| { | ||||
|  | ||||
|     private String message; | ||||
|     private byte position; | ||||
|  | ||||
|     @Override | ||||
|     public void read(ByteBuf buf) | ||||
|     public Chat(String message) | ||||
|     { | ||||
|         message = readString( buf ); | ||||
|         this( message, (byte) 0 ); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void write(ByteBuf buf) | ||||
|     public void read(ByteBuf buf, Protocol.ProtocolDirection direction, int protocolVersion) | ||||
|     { | ||||
|         message = readString( buf ); | ||||
|         if ( direction.toString().equals( "TO_CLIENT" ) && protocolVersion >= 5 ) | ||||
|         { | ||||
|             position = buf.readByte(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void write(ByteBuf buf, Protocol.ProtocolDirection direction, int protocolVersion) | ||||
|     { | ||||
|         writeString( message, buf ); | ||||
|         if ( direction.toString().equals( "TO_CLIENT" ) && protocolVersion >= 5 ) | ||||
|         { | ||||
|             buf.writeByte( position ); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|   | ||||
| @@ -7,6 +7,7 @@ import lombok.Data; | ||||
| import lombok.EqualsAndHashCode; | ||||
| import lombok.NoArgsConstructor; | ||||
| import net.md_5.bungee.protocol.AbstractPacketHandler; | ||||
| import net.md_5.bungee.protocol.Protocol; | ||||
|  | ||||
| @Data | ||||
| @NoArgsConstructor | ||||
| @@ -20,28 +21,34 @@ public class ClientSettings extends DefinedPacket | ||||
|     private byte chatFlags; | ||||
|     private boolean unknown; | ||||
|     private byte difficulty; | ||||
|     private boolean showCape; | ||||
|     private byte showCape; | ||||
|  | ||||
|     @Override | ||||
|     public void read(ByteBuf buf) | ||||
|     public void read(ByteBuf buf, Protocol.ProtocolDirection direction, int protocolVersion) | ||||
|     { | ||||
|         locale = readString( buf ); | ||||
|         viewDistance = buf.readByte(); | ||||
|         chatFlags = buf.readByte(); | ||||
|         unknown = buf.readBoolean(); | ||||
|         if ( protocolVersion < 5 ) | ||||
|         { | ||||
|             difficulty = buf.readByte(); | ||||
|         showCape = buf.readBoolean(); | ||||
|         } | ||||
|         showCape = buf.readByte(); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void write(ByteBuf buf) | ||||
|     public void write(ByteBuf buf, Protocol.ProtocolDirection direction, int protocolVersion) | ||||
|     { | ||||
|         writeString( locale, buf ); | ||||
|         buf.writeByte( viewDistance ); | ||||
|         buf.writeByte( chatFlags ); | ||||
|         buf.writeBoolean( unknown ); | ||||
|         if ( protocolVersion < 5 ) | ||||
|         { | ||||
|             buf.writeByte( difficulty ); | ||||
|         buf.writeBoolean( showCape ); | ||||
|         } | ||||
|         buf.writeByte( showCape ); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|   | ||||
| @@ -7,6 +7,7 @@ import lombok.Data; | ||||
| import lombok.EqualsAndHashCode; | ||||
| import lombok.NoArgsConstructor; | ||||
| import net.md_5.bungee.protocol.AbstractPacketHandler; | ||||
| import net.md_5.bungee.protocol.Protocol; | ||||
|  | ||||
| @Data | ||||
| @NoArgsConstructor | ||||
| @@ -24,28 +25,40 @@ public class ScoreboardScore extends DefinedPacket | ||||
|     private int value; | ||||
|  | ||||
|     @Override | ||||
|     public void read(ByteBuf buf) | ||||
|     public void read(ByteBuf buf, Protocol.ProtocolDirection direction, int protocolVersion) | ||||
|     { | ||||
|         itemName = readString( buf ); | ||||
|         action = buf.readByte(); | ||||
|         if ( action != 1 ) | ||||
|         { | ||||
|             scoreName = readString( buf ); | ||||
|             if ( protocolVersion >= 7 ) | ||||
|             { | ||||
|                 value = readVarInt( buf ); | ||||
|             } else | ||||
|             { | ||||
|                 value = buf.readInt(); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void write(ByteBuf buf) | ||||
|     public void write(ByteBuf buf, Protocol.ProtocolDirection direction, int protocolVersion) | ||||
|     { | ||||
|         writeString( itemName, buf ); | ||||
|         buf.writeByte( action ); | ||||
|         if ( action != 1 ) | ||||
|         { | ||||
|             writeString( scoreName, buf ); | ||||
|             if ( protocolVersion >= 7 ) | ||||
|             { | ||||
|                 writeVarInt( value, buf ); | ||||
|             } else | ||||
|             { | ||||
|                 buf.writeInt( value ); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void handle(AbstractPacketHandler handler) throws Exception | ||||
|   | ||||
| @@ -7,6 +7,7 @@ import lombok.Data; | ||||
| import lombok.EqualsAndHashCode; | ||||
| import lombok.NoArgsConstructor; | ||||
| import net.md_5.bungee.protocol.AbstractPacketHandler; | ||||
| import net.md_5.bungee.protocol.Protocol; | ||||
|  | ||||
| @Data | ||||
| @NoArgsConstructor | ||||
| @@ -40,7 +41,7 @@ public class Team extends DefinedPacket | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void read(ByteBuf buf) | ||||
|     public void read(ByteBuf buf, Protocol.ProtocolDirection direction, int protocolVersion) | ||||
|     { | ||||
|         name = readString( buf ); | ||||
|         mode = buf.readByte(); | ||||
| @@ -53,8 +54,9 @@ public class Team extends DefinedPacket | ||||
|         } | ||||
|         if ( mode == 0 || mode == 3 || mode == 4 ) | ||||
|         { | ||||
|             players = new String[ buf.readShort() ]; | ||||
|             for ( int i = 0; i < getPlayers().length; i++ ) | ||||
|             int len = ( protocolVersion >= 7 ) ? readVarInt( buf ) : buf.readInt(); | ||||
|             players = new String[ len ]; | ||||
|             for ( int i = 0; i < len; i++ ) | ||||
|             { | ||||
|                 players[i] = readString( buf ); | ||||
|             } | ||||
| @@ -62,7 +64,7 @@ public class Team extends DefinedPacket | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void write(ByteBuf buf) | ||||
|     public void write(ByteBuf buf, Protocol.ProtocolDirection direction, int protocolVersion) | ||||
|     { | ||||
|         writeString( name, buf ); | ||||
|         buf.writeByte( mode ); | ||||
| @@ -75,10 +77,16 @@ public class Team extends DefinedPacket | ||||
|         } | ||||
|         if ( mode == 0 || mode == 3 || mode == 4 ) | ||||
|         { | ||||
|             buf.writeShort( players.length ); | ||||
|             for ( int i = 0; i < players.length; i++ ) | ||||
|             if ( protocolVersion >= 7 ) | ||||
|             { | ||||
|                 writeString( players[i], buf ); | ||||
|                 writeVarInt( players.length, buf ); | ||||
|             } else | ||||
|             { | ||||
|                 buf.writeShort( players.length ); | ||||
|             } | ||||
|             for ( String player : players ) | ||||
|             { | ||||
|                 writeString( player, buf ); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|   | ||||
| @@ -469,13 +469,13 @@ public class BungeeCord extends ProxyServer | ||||
|     @Override | ||||
|     public int getProtocolVersion() | ||||
|     { | ||||
|         return Protocol.PROTOCOL_VERSION; | ||||
|         return Protocol.supportedVersions.get( Protocol.supportedVersions.size() - 1 ); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public String getGameVersion() | ||||
|     { | ||||
|         return Protocol.MINECRAFT_VERSION; | ||||
|         return "1.7.4"; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|   | ||||
| @@ -216,8 +216,8 @@ public final class UserConnection implements ProxiedPlayer | ||||
|             protected void initChannel(Channel ch) throws Exception | ||||
|             { | ||||
|                 PipelineUtils.BASE.initChannel( ch ); | ||||
|                 ch.pipeline().addAfter( PipelineUtils.FRAME_DECODER, PipelineUtils.PACKET_DECODER, new MinecraftDecoder( Protocol.HANDSHAKE, false ) ); | ||||
|                 ch.pipeline().addAfter( PipelineUtils.FRAME_PREPENDER, PipelineUtils.PACKET_ENCODER, new MinecraftEncoder( Protocol.HANDSHAKE, false ) ); | ||||
|                 ch.pipeline().addAfter( PipelineUtils.FRAME_DECODER, PipelineUtils.PACKET_DECODER, new MinecraftDecoder( Protocol.HANDSHAKE, false, getPendingConnection().getVersion() ) ); | ||||
|                 ch.pipeline().addAfter( PipelineUtils.FRAME_PREPENDER, PipelineUtils.PACKET_ENCODER, new MinecraftEncoder( Protocol.HANDSHAKE, false, getPendingConnection().getVersion() ) ); | ||||
|                 ch.pipeline().get( HandlerBoss.class ).setHandler( new ServerConnector( bungee, UserConnection.this, target ) ); | ||||
|             } | ||||
|         }; | ||||
|   | ||||
| @@ -175,8 +175,9 @@ public class InitialHandler extends PacketHandler implements PendingConnection | ||||
|             forced.ping( pingBack ); | ||||
|         } else | ||||
|         { | ||||
|             int protocol = ( Protocol.supportedVersions.contains( handshake.getProtocolVersion() ) ) ? handshake.getProtocolVersion() : -1; | ||||
|             pingBack.done( new ServerPing( | ||||
|                     new ServerPing.Protocol( bungee.getGameVersion(), bungee.getProtocolVersion() ), | ||||
|                     new ServerPing.Protocol( bungee.getGameVersion(), protocol ), | ||||
|                     new ServerPing.Players( listener.getMaxPlayers(), bungee.getOnlineCount(), null ), | ||||
|                     motd, BungeeCord.getInstance().config.favicon ), | ||||
|                     null ); | ||||
| @@ -198,6 +199,7 @@ public class InitialHandler extends PacketHandler implements PendingConnection | ||||
|     { | ||||
|         Preconditions.checkState( thisState == State.HANDSHAKE, "Not expecting HANDSHAKE" ); | ||||
|         this.handshake = handshake; | ||||
|         ch.setVersion( handshake.getProtocolVersion() ); | ||||
|  | ||||
|         // SRV records can end with a . depending on DNS / client. | ||||
|         if ( handshake.getHost().endsWith( "." ) ) | ||||
| @@ -233,14 +235,10 @@ public class InitialHandler extends PacketHandler implements PendingConnection | ||||
|         Preconditions.checkState( thisState == State.USERNAME, "Not expecting USERNAME" ); | ||||
|         this.loginRequest = loginRequest; | ||||
|  | ||||
|         if ( handshake.getProtocolVersion() > bungee.getProtocolVersion() ) | ||||
|         if ( !Protocol.supportedVersions.contains( handshake.getProtocolVersion() ) ) | ||||
|         { | ||||
|             disconnect( bungee.getTranslation( "outdated_server" ) ); | ||||
|             return; | ||||
|         } else if ( handshake.getProtocolVersion() < bungee.getProtocolVersion() ) | ||||
|         { | ||||
|             disconnect( bungee.getTranslation( "outdated_client" ) ); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if ( getName().length() > 16 ) | ||||
|   | ||||
| @@ -3,6 +3,7 @@ package net.md_5.bungee.connection; | ||||
| import lombok.RequiredArgsConstructor; | ||||
| import net.md_5.bungee.BungeeCord; | ||||
| import net.md_5.bungee.api.Callback; | ||||
| import net.md_5.bungee.api.ProxyServer; | ||||
| import net.md_5.bungee.api.ServerPing; | ||||
| import net.md_5.bungee.api.config.ServerInfo; | ||||
| import net.md_5.bungee.netty.ChannelWrapper; | ||||
| @@ -27,12 +28,12 @@ public class PingHandler extends PacketHandler | ||||
|     public void connected(ChannelWrapper channel) throws Exception | ||||
|     { | ||||
|         this.channel = channel; | ||||
|         MinecraftEncoder encoder = new MinecraftEncoder( Protocol.HANDSHAKE, false ); | ||||
|         MinecraftEncoder encoder = new MinecraftEncoder( Protocol.HANDSHAKE, false, ProxyServer.getInstance().getProtocolVersion() ); | ||||
|  | ||||
|         channel.getHandle().pipeline().addAfter( PipelineUtils.FRAME_DECODER, PipelineUtils.PACKET_DECODER, new MinecraftDecoder( Protocol.STATUS, false ) ); | ||||
|         channel.getHandle().pipeline().addAfter( PipelineUtils.FRAME_DECODER, PipelineUtils.PACKET_DECODER, new MinecraftDecoder( Protocol.STATUS, false, ProxyServer.getInstance().getProtocolVersion() ) ); | ||||
|         channel.getHandle().pipeline().addAfter( PipelineUtils.FRAME_PREPENDER, PipelineUtils.PACKET_ENCODER, encoder ); | ||||
|  | ||||
|         channel.write( new Handshake( Protocol.PROTOCOL_VERSION, target.getAddress().getHostString(), target.getAddress().getPort(), 1 ) ); | ||||
|         channel.write( new Handshake( ProxyServer.getInstance().getProtocolVersion(), target.getAddress().getHostString(), target.getAddress().getPort(), 1 ) ); | ||||
|  | ||||
|         encoder.setProtocol( Protocol.STATUS ); | ||||
|         channel.write( new StatusRequest() ); | ||||
|   | ||||
| @@ -28,6 +28,12 @@ public class ChannelWrapper | ||||
|         ch.pipeline().get( MinecraftEncoder.class ).setProtocol( protocol ); | ||||
|     } | ||||
|  | ||||
|     public void setVersion(int protocol) | ||||
|     { | ||||
|         ch.pipeline().get( MinecraftDecoder.class ).setProtocolVersion( protocol ); | ||||
|         ch.pipeline().get( MinecraftEncoder.class ).setProtocolVersion( protocol ); | ||||
|     } | ||||
|  | ||||
|     public synchronized void write(Object packet) | ||||
|     { | ||||
|         if ( !closed ) | ||||
|   | ||||
| @@ -43,8 +43,8 @@ public class PipelineUtils | ||||
|  | ||||
|             BASE.initChannel( ch ); | ||||
|             ch.pipeline().addBefore( FRAME_DECODER, LEGACY_DECODER, new LegacyDecoder() ); | ||||
|             ch.pipeline().addAfter( FRAME_DECODER, PACKET_DECODER, new MinecraftDecoder( Protocol.HANDSHAKE, true ) ); | ||||
|             ch.pipeline().addAfter( FRAME_PREPENDER, PACKET_ENCODER, new MinecraftEncoder( Protocol.HANDSHAKE, true ) ); | ||||
|             ch.pipeline().addAfter( FRAME_DECODER, PACKET_DECODER, new MinecraftDecoder( Protocol.HANDSHAKE, true, ProxyServer.getInstance().getProtocolVersion() ) ); | ||||
|             ch.pipeline().addAfter( FRAME_PREPENDER, PACKET_ENCODER, new MinecraftEncoder( Protocol.HANDSHAKE, true, ProxyServer.getInstance().getProtocolVersion() ) ); | ||||
|             ch.pipeline().addBefore( FRAME_PREPENDER, LEGACY_KICKER, new KickStringWriter() ); | ||||
|             ch.pipeline().get( HandlerBoss.class ).setHandler( new InitialHandler( ProxyServer.getInstance(), ch.attr( LISTENER ).get() ) ); | ||||
|         } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 md_5
					md_5