Waterfall/Waterfall-Proxy-Patches/0004-1.7.x-Protocol-Patch.patch

1976 lines
82 KiB
Diff

From 889411e2ea36b2edcb33869e480258701b9be30c Mon Sep 17 00:00:00 2001
From: Troy Frew <fuzzy_bot@arenaga.me>
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 00000000..90064112
--- /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 10e16d79..04a34033 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
@@ -193,6 +193,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" );
@@ -203,6 +208,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 9e9ea49c..75b0f8a9 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
@@ -5,10 +5,11 @@ import io.netty.buffer.ByteBufUtil;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.DecoderException;
import io.netty.handler.codec.MessageToMessageDecoder;
-import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Setter;
+import java.util.List;
+
@AllArgsConstructor
public class MinecraftDecoder extends MessageToMessageDecoder<ByteBuf>
{
@@ -43,7 +44,7 @@ public class MinecraftDecoder extends MessageToMessageDecoder<ByteBuf>
if ( packet != null )
{
packetTypeInfo = packet.getClass();
- 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 d4b03843..9aac7ca9 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<DefinedPacket>
{
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 8e40682c..eba86548 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
@@ -378,6 +378,8 @@ public enum Protocol
private final TIntObjectMap<List<Integer>> linkedProtocols = new TIntObjectHashMap<>();
{
linkedProtocols.put( ProtocolConstants.MINECRAFT_1_8, Arrays.asList(
+ ProtocolConstants.MINECRAFT_1_7_2,
+ ProtocolConstants.MINECRAFT_1_7_6,
ProtocolConstants.MINECRAFT_1_9,
ProtocolConstants.MINECRAFT_1_12,
ProtocolConstants.MINECRAFT_1_13
@@ -431,7 +433,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 " );
+ }
}
Constructor<? extends DefinedPacket> constructor = protocolData.packetConstructors[id];
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 c23b1947..b461e94e 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;
@@ -19,6 +21,7 @@ public class ProtocolConstants
public static final int MINECRAFT_1_12_2 = 340;
public static final int MINECRAFT_1_13 = 393;
public static final List<String> SUPPORTED_VERSIONS = Arrays.asList(
+ "1.7.x",
"1.8.x",
"1.9.x",
"1.10.x",
@@ -27,6 +30,8 @@ public class ProtocolConstants
"1.13.x"
);
public static final List<Integer> 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 29e54dba..1f9e64dc 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
@@ -7,10 +7,12 @@ 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
@@ -33,7 +35,15 @@ public class Varint21FrameDecoder extends ByteToMessageDecoder
int length = DefinedPacket.readVarInt( Unpooled.wrappedBuffer( buf ) );
if ( length == 0 )
{
- 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 95ad39b7..1f78125a 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,6 +1,6 @@
package net.md_5.bungee.protocol.packet;
-import net.md_5.bungee.protocol.DefinedPacket;
+import io.github.waterfallmc.travertine.protocol.MultiVersionPacketV17;
import io.netty.buffer.ByteBuf;
import lombok.AllArgsConstructor;
import lombok.Data;
@@ -13,7 +13,7 @@ import net.md_5.bungee.protocol.ProtocolConstants;
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = false)
-public class Chat extends DefinedPacket
+public class Chat extends MultiVersionPacketV17
{
private String message;
@@ -24,6 +24,14 @@ public class Chat extends DefinedPacket
this( message, (byte) 0 );
}
+ // 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)
{
@@ -34,6 +42,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 5c79727c..431b2eb8 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,6 @@
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;
@@ -13,7 +14,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 +25,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 +72,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 a29524ca..8d9f4ccb 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 06676e42..19a85492 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,6 +1,6 @@
package net.md_5.bungee.protocol.packet;
-import net.md_5.bungee.protocol.DefinedPacket;
+import io.github.waterfallmc.travertine.protocol.MultiVersionPacketV17;
import io.netty.buffer.ByteBuf;
import lombok.AllArgsConstructor;
import lombok.Data;
@@ -13,12 +13,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 +35,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 d11a9ea9..07fc21b6 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 7ed2dc3a..9f8d56fc 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 9df9ef56..56e6e522 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,6 +1,6 @@
package net.md_5.bungee.protocol.packet;
-import net.md_5.bungee.protocol.DefinedPacket;
+import io.github.waterfallmc.travertine.protocol.MultiVersionPacketV17;
import io.netty.buffer.ByteBuf;
import lombok.AllArgsConstructor;
import lombok.Data;
@@ -13,17 +13,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/PlayerListItem.java b/protocol/src/main/java/net/md_5/bungee/protocol/packet/PlayerListItem.java
index 9983ef2e..ae5dad52 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,6 @@
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.Data;
@@ -13,12 +14,24 @@ import java.util.UUID;
@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)
{
@@ -73,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 0e06b49d..ac7451dc 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,8 +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 net.md_5.bungee.protocol.DefinedPacket;
import io.netty.buffer.ByteBuf;
import java.io.ByteArrayInputStream;
import java.io.DataInput;
@@ -21,7 +21,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<String, String> MODERNISE = new Function<String, String>()
@@ -79,6 +79,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 +98,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 6279d9f3..b4a66baf 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,6 +1,7 @@
package net.md_5.bungee.protocol.packet;
import net.md_5.bungee.protocol.DefinedPacket;
+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 6f0de535..b967f89f 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,6 +1,6 @@
package net.md_5.bungee.protocol.packet;
-import net.md_5.bungee.protocol.DefinedPacket;
+import io.github.waterfallmc.travertine.protocol.MultiVersionPacketV17;
import io.netty.buffer.ByteBuf;
import lombok.AllArgsConstructor;
import lombok.Data;
@@ -13,7 +13,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 +24,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 +50,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 f9eaa7ce..e174ac0b 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,6 +1,6 @@
package net.md_5.bungee.protocol.packet;
-import net.md_5.bungee.protocol.DefinedPacket;
+import io.github.waterfallmc.travertine.protocol.MultiVersionPacketV17;
import io.netty.buffer.ByteBuf;
import lombok.Data;
import lombok.EqualsAndHashCode;
@@ -11,7 +11,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 +33,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 +64,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 f93508d9..13af5112 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,6 +1,7 @@
package net.md_5.bungee.protocol.packet;
import net.md_5.bungee.protocol.DefinedPacket;
+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;
@@ -39,6 +40,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)
{
@@ -76,6 +102,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 bea13ea8..22622c56 100644
--- a/proxy/src/main/java/net/md_5/bungee/BungeeCord.java
+++ b/proxy/src/main/java/net/md_5/bungee/BungeeCord.java
@@ -163,6 +163,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 494213db..1d89acf5 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 491cf1a1..299a216c 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<ServerPing.PlayerInfo>, JsonDeserializer<ServerPing.PlayerInfo>
{
+ // 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<ServerPing.PlayerInf
{
JsonObject out = new JsonObject();
out.addProperty( "name", src.getName() );
- out.addProperty( "id", src.getUniqueId().toString() );
+ // Travertine start
+ if ( ProtocolConstants.isBeforeOrEq( protocol, ProtocolConstants.MINECRAFT_1_7_2 ) )
+ {
+ out.addProperty( "id", src.getId() );
+ } else
+ {
+ out.addProperty( "id", src.getUniqueId().toString() );
+ }
+ // Travertine end
return out;
}
}
diff --git a/proxy/src/main/java/net/md_5/bungee/ServerConnector.java b/proxy/src/main/java/net/md_5/bungee/ServerConnector.java
index 0937c39d..28d63f52 100644
--- a/proxy/src/main/java/net/md_5/bungee/ServerConnector.java
+++ b/proxy/src/main/java/net/md_5/bungee/ServerConnector.java
@@ -3,6 +3,8 @@ package net.md_5.bungee;
import com.google.common.base.Preconditions;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
+
+import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Queue;
import java.util.Set;
@@ -245,10 +247,20 @@ public class ServerConnector extends PacketHandler
user.unsafe().sendPacket( modLogin );
- ByteBuf brand = ByteBufAllocator.DEFAULT.heapBuffer();
- DefinedPacket.writeString( bungee.getName() + " (" + bungee.getVersion() + ")", brand );
- user.unsafe().sendPacket( new PluginMessage( user.getPendingConnection().getVersion() >= 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() );
} else
@@ -259,7 +271,7 @@ public class ServerConnector extends PacketHandler
Scoreboard serverScoreboard = user.getServerSentScoreboard();
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() )
{
@@ -392,14 +404,23 @@ 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;
}
+ }else
+ {
+ // We have to forward these to the user, especially with Forge as stuff might break
+ // This includes any REGISTER messages we intercepted earlier.
+ user.unsafe().sendPacket( pluginMessage );
}
-
- // We have to forward these to the user, especially with Forge as stuff might break
- // This includes any REGISTER messages we intercepted earlier.
- user.unsafe().sendPacket( pluginMessage );
}
@Override
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 ef12a019..4a1c3638 100644
--- a/proxy/src/main/java/net/md_5/bungee/UserConnection.java
+++ b/proxy/src/main/java/net/md_5/bungee/UserConnection.java
@@ -195,6 +195,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;
}
@@ -453,7 +454,7 @@ public final class UserConnection implements ProxiedPlayer
message = ChatComponentTransformer.getInstance().transform( this, message );
// Action bar doesn't display the new JSON formattings, legacy works - send it using this for now
- if ( position == ChatMessageType.ACTION_BAR )
+ if ( position == ChatMessageType.ACTION_BAR && getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_8 ) // Travertine
{
sendMessage( position, ComponentSerializer.toString( new TextComponent( BaseComponent.toLegacyText( message ) ) ) );
} else
@@ -468,7 +469,7 @@ public final class UserConnection implements ProxiedPlayer
message = ChatComponentTransformer.getInstance().transform( this, message )[0];
// Action bar doesn't display the new JSON formattings, legacy works - send it using this for now
- if ( position == ChatMessageType.ACTION_BAR )
+ if ( position == ChatMessageType.ACTION_BAR && getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_8 ) // Travertine
{
sendMessage( position, ComponentSerializer.toString( new TextComponent( BaseComponent.toLegacyText( message ) ) ) );
} else
@@ -647,6 +648,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, header )[0];
footer = ChatComponentTransformer.getInstance().transform( this, footer )[0];
@@ -659,6 +661,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, header );
footer = ChatComponentTransformer.getInstance().transform( this, footer );
@@ -688,6 +691,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 76dc13aa..242efd91 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
@@ -144,7 +144,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() );
@@ -154,7 +154,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:
@@ -251,16 +251,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() + " (" + bungee.getVersion() + ")" + " <- " + serverBrand, brand );
- 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() + " (" + bungee.getVersion() + ")" + " <- " + serverBrand, brand);
+ pluginMessage.setData(brand);
+ brand.release();
+ } catch (Exception ProtocolHacksSuck)
+ {
+ return;
+ }
+ } else
+ {
+ String serverBrand = new String( pluginMessage.getData(), "UTF-8" );
+ pluginMessage.setData( ( bungee.getName() + " (" + bungee.getVersion() + ")" + " <- " + serverBrand ).getBytes( "UTF-8" ) );
+ }
+ // 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 c6e109c5..adcdd31c 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
@@ -13,6 +13,13 @@ import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import javax.crypto.SecretKey;
+
+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 lombok.Getter;
import lombok.RequiredArgsConstructor;
import net.md_5.bungee.BungeeCord;
@@ -234,8 +241,24 @@ 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
+ // 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
}
};
@@ -521,7 +544,15 @@ public class InitialHandler extends PacketHandler implements PendingConnection
userCon.setCompressionThreshold( BungeeCord.getInstance().config.getCompressionThreshold() );
userCon.init();
- unsafe.sendPacket( new LoginSuccess( getUniqueId().toString(), getName() ) ); // With dashes in between
+ // Travertine start
+ if ( ProtocolConstants.isAfterOrEq( getVersion() , ProtocolConstants.MINECRAFT_1_7_6 ) )
+ {
+ unsafe.sendPacket( new LoginSuccess( getUniqueId().toString(), getName() ) ); // With dashes in between
+ } else
+ {
+ unsafe.sendPacket( new LoginSuccess( getUUID(), getName() ) ); // Without dashes, for older clients.
+ }
+ // Travertine end
ch.setProtocol( Protocol.GAME );
ch.getHandle().pipeline().get( HandlerBoss.class ).setHandler( new UpstreamBridge( bungee, userCon ) );
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 76f496ce..eab2523d 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
@@ -15,6 +15,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;
@@ -63,7 +64,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
callback.done( gson.fromJson( statusResponse.getResponse(), ServerPing.class ), null );
channel.close();
}
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 7129f5e7..6440db3a 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
@@ -79,7 +79,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 4df06119..b1d2714c 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
@@ -29,6 +29,10 @@ public abstract class EntityMap
{
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.java.orig b/proxy/src/main/java/net/md_5/bungee/entitymap/EntityMap.java.orig
new file mode 100644
index 00000000..d98a8056
--- /dev/null
+++ b/proxy/src/main/java/net/md_5/bungee/entitymap/EntityMap.java.orig
@@ -0,0 +1,215 @@
+package net.md_5.bungee.entitymap;
+
+import com.flowpowered.nbt.stream.NBTInputStream;
+import com.google.common.base.Throwables;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.ByteBufInputStream;
+import java.io.IOException;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import net.md_5.bungee.protocol.DefinedPacket;
+import net.md_5.bungee.protocol.ProtocolConstants;
+
+/**
+ * Class to rewrite integers within packets.
+ */
+@NoArgsConstructor(access = AccessLevel.PACKAGE)
+public abstract class EntityMap
+{
+
+ private final boolean[] clientboundInts = new boolean[ 256 ];
+ private final boolean[] clientboundVarInts = new boolean[ 256 ];
+
+ private final boolean[] serverboundInts = new boolean[ 256 ];
+ private final boolean[] serverboundVarInts = new boolean[ 256 ];
+
+ // Returns the correct entity map for the protocol version
+ public static EntityMap getEntityMap(int version)
+ {
+ switch ( version )
+ {
+ case ProtocolConstants.MINECRAFT_1_8:
+ return EntityMap_1_8.INSTANCE;
+ case ProtocolConstants.MINECRAFT_1_9:
+ case ProtocolConstants.MINECRAFT_1_9_1:
+ case ProtocolConstants.MINECRAFT_1_9_2:
+ return EntityMap_1_9.INSTANCE;
+ case ProtocolConstants.MINECRAFT_1_9_4:
+ return EntityMap_1_9_4.INSTANCE;
+ case ProtocolConstants.MINECRAFT_1_10:
+ return EntityMap_1_10.INSTANCE;
+ case ProtocolConstants.MINECRAFT_1_11:
+ case ProtocolConstants.MINECRAFT_1_11_1:
+ return EntityMap_1_11.INSTANCE;
+ }
+ throw new RuntimeException( "Version " + version + " has no entity map" );
+ }
+
+ protected void addRewrite(int id, ProtocolConstants.Direction direction, boolean varint)
+ {
+ if ( direction == ProtocolConstants.Direction.TO_CLIENT )
+ {
+ if ( varint )
+ {
+ clientboundVarInts[id] = true;
+ } else
+ {
+ clientboundInts[id] = true;
+ }
+ } else if ( varint )
+ {
+ serverboundVarInts[id] = true;
+ } else
+ {
+ serverboundInts[id] = true;
+ }
+ }
+
+ public void rewriteServerbound(ByteBuf packet, int oldId, int newId)
+ {
+ rewrite( packet, oldId, newId, serverboundInts, serverboundVarInts );
+ }
+
+ public void rewriteClientbound(ByteBuf packet, int oldId, int newId)
+ {
+ rewrite( packet, oldId, newId, clientboundInts, clientboundVarInts );
+ }
+
+ protected static void rewriteInt(ByteBuf packet, int oldId, int newId, int offset)
+ {
+ int readId = packet.getInt( offset );
+ if ( readId == oldId )
+ {
+ packet.setInt( offset, newId );
+ } else if ( readId == newId )
+ {
+ packet.setInt( offset, oldId );
+ }
+ }
+
+ @SuppressFBWarnings("DLS_DEAD_LOCAL_STORE")
+ protected static void rewriteVarInt(ByteBuf packet, int oldId, int newId, int offset)
+ {
+ // Need to rewrite the packet because VarInts are variable length
+ int readId = DefinedPacket.readVarInt( packet );
+ int readIdLength = packet.readerIndex() - offset;
+ if ( readId == oldId || readId == newId )
+ {
+ ByteBuf data = packet.copy();
+ packet.readerIndex( offset );
+ packet.writerIndex( offset );
+ DefinedPacket.writeVarInt( readId == oldId ? newId : oldId, packet );
+ packet.writeBytes( data );
+ data.release();
+ }
+ }
+
+ protected static void rewriteMetaVarInt(ByteBuf packet, int oldId, int newId, int metaIndex)
+ {
+ int readerIndex = packet.readerIndex();
+
+ short index;
+ while ( ( index = packet.readUnsignedByte() ) != 0xFF )
+ {
+ int type = DefinedPacket.readVarInt( packet );
+
+ switch ( type )
+ {
+ case 0:
+ packet.skipBytes( 1 ); // byte
+ break;
+ case 1:
+ if ( index == metaIndex )
+ {
+ int position = packet.readerIndex();
+ rewriteVarInt( packet, oldId, newId, position );
+ packet.readerIndex( position );
+ }
+ DefinedPacket.readVarInt( packet );
+ break;
+ case 2:
+ packet.skipBytes( 4 ); // float
+ break;
+ case 3:
+ case 4:
+ DefinedPacket.readString( packet );
+ break;
+ case 5:
+ if ( packet.readShort() != -1 )
+ {
+ packet.skipBytes( 3 ); // byte, short
+
+ int position = packet.readerIndex();
+ if ( packet.readByte() != 0 )
+ {
+ packet.readerIndex( position );
+
+ try
+ {
+ new NBTInputStream( new ByteBufInputStream( packet ), false ).readTag();
+ } catch ( IOException ex )
+ {
+ throw Throwables.propagate( ex );
+ }
+ }
+ }
+ break;
+ case 6:
+ packet.skipBytes( 1 ); // boolean
+ break;
+ case 7:
+ packet.skipBytes( 12 ); // float, float, float
+ break;
+ case 8:
+ packet.readLong();
+ break;
+ case 9:
+ if ( packet.readBoolean() )
+ {
+ packet.skipBytes( 8 ); // long
+ }
+ break;
+ case 10:
+ DefinedPacket.readVarInt( packet );
+ break;
+ case 11:
+ if ( packet.readBoolean() )
+ {
+ packet.skipBytes( 16 ); // long, long
+ }
+ break;
+ case 12:
+ DefinedPacket.readVarInt( packet );
+ break;
+ default:
+ throw new IllegalArgumentException( "Unknown meta type " + type );
+ }
+ }
+
+ packet.readerIndex( readerIndex );
+ }
+
+ // Handles simple packets
+ private static void rewrite(ByteBuf packet, int oldId, int newId, boolean[] ints, boolean[] varints)
+ {
+ int readerIndex = packet.readerIndex();
+ int packetId = DefinedPacket.readVarInt( packet );
+ int packetIdLength = packet.readerIndex() - readerIndex;
+
+ if (packetId < 0 || packetId > ints.length || packetId > varints.length) { // Invalid packet id
+ // Ignore these invalid packets for compatibility reasons
+ packet.readerIndex( readerIndex );
+ return;
+ }
+
+ if ( ints[packetId] )
+ {
+ rewriteInt( packet, oldId, newId, readerIndex + packetIdLength );
+ } else if ( varints[packetId] )
+ {
+ rewriteVarInt( packet, oldId, newId, readerIndex + packetIdLength );
+ }
+ packet.readerIndex( readerIndex );
+ }
+}
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 00000000..65c1a9ec
--- /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 00000000..6755fe84
--- /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 c1272da3..45af7ea4 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.
*/
@@ -173,4 +180,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 <code>true</code> if the user's FML build is outdated, otherwise
+ * <code>false</code>
+ */
+ 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 5e02f8c8..e3c1b9b9 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<ForgeClientH
// Once we've done it, no point doing it again.
Map<String, String> 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 daf12f74..e33861ab 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<UUID> uuids = new HashSet<>();
+ private final Collection<String> 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.18.0