From 12a7b7afc35542deb4a66ad468634fd2931c9e04 Mon Sep 17 00:00:00 2001 From: Thinkofdeath Date: Tue, 1 Mar 2016 09:13:13 +1100 Subject: [PATCH] Add support for 15w33c and multiple fallback servers --- .../bungee/protocol/MinecraftDecoder.java | 2 +- .../bungee/protocol/MinecraftEncoder.java | 2 +- .../net/md_5/bungee/protocol/Protocol.java | 53 ++++- .../bungee/protocol/ProtocolConstants.java | 9 +- .../protocol/packet/ClientSettings.java | 21 +- .../main/java/net/md_5/bungee/BungeeCord.java | 3 +- .../java/net/md_5/bungee/ServerConnector.java | 23 ++- .../java/net/md_5/bungee/UserConnection.java | 48 +++-- .../net/md_5/bungee/entitymap/EntityMap.java | 2 + .../md_5/bungee/entitymap/EntityMap_1_8.java | 16 -- .../bungee/entitymap/EntityMap_SNAPSHOT.java | 181 ++++++++++++++++++ .../md_5/bungee/forge/ForgeClientHandler.java | 28 --- .../forge/ForgeClientHandshakeState.java | 11 -- 13 files changed, 306 insertions(+), 93 deletions(-) create mode 100644 proxy/src/main/java/net/md_5/bungee/entitymap/EntityMap_SNAPSHOT.java 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 5719e188..e7cb3803 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 @@ -27,7 +27,7 @@ public class MinecraftDecoder extends MessageToMessageDecoder { int packetId = DefinedPacket.readVarInt( in ); - DefinedPacket packet = prot.createPacket( packetId ); + DefinedPacket packet = prot.createPacket( packetId, protocolVersion ); if ( packet != null ) { packet.read( in, prot.getDirection(), protocolVersion ); 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 242a9da1..d4b03843 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 @@ -20,7 +20,7 @@ public class MinecraftEncoder extends MessageToByteEncoder protected void encode(ChannelHandlerContext ctx, DefinedPacket msg, ByteBuf out) throws Exception { Protocol.DirectionData prot = ( server ) ? protocol.TO_CLIENT : protocol.TO_SERVER; - DefinedPacket.writeVarInt( prot.getId( msg.getClass() ), out ); + DefinedPacket.writeVarInt( prot.getId( msg.getClass(), protocolVersion ), out ); msg.write( 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 d7aaee54..85d1a2c4 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 @@ -1,7 +1,11 @@ package net.md_5.bungee.protocol; import com.google.common.base.Preconditions; +import gnu.trove.map.TIntIntMap; +import gnu.trove.map.TIntObjectMap; import gnu.trove.map.TObjectIntMap; +import gnu.trove.map.hash.TIntIntHashMap; +import gnu.trove.map.hash.TIntObjectHashMap; import gnu.trove.map.hash.TObjectIntHashMap; import java.lang.reflect.Constructor; import java.util.Arrays; @@ -68,9 +72,9 @@ public enum Protocol TO_SERVER.registerPacket( 0x00, KeepAlive.class ); TO_SERVER.registerPacket( 0x01, Chat.class ); - TO_SERVER.registerPacket( 0x14, TabCompleteRequest.class ); - TO_SERVER.registerPacket( 0x15, ClientSettings.class ); - TO_SERVER.registerPacket( 0x17, PluginMessage.class ); + TO_SERVER.registerPacket( 0x14, 0x15, TabCompleteRequest.class ); + TO_SERVER.registerPacket( 0x15, 0x16, ClientSettings.class ); + TO_SERVER.registerPacket( 0x17, 0x18, PluginMessage.class ); } }, // 1 @@ -119,8 +123,27 @@ public enum Protocol private final Class[] packetClasses = new Class[ MAX_PACKET_ID ]; private final Constructor[] packetConstructors = new Constructor[ MAX_PACKET_ID ]; - public final DefinedPacket createPacket(int id) + private final TIntObjectMap packetRemap = new TIntObjectHashMap<>(); + private final TIntObjectMap packetRemapInv = new TIntObjectHashMap<>(); + { + packetRemap.put( ProtocolConstants.MINECRAFT_1_8, new TIntIntHashMap() ); + packetRemapInv.put( ProtocolConstants.MINECRAFT_1_8, new TIntIntHashMap() ); + packetRemap.put( ProtocolConstants.MINECRAFT_SNAPSHOT, new TIntIntHashMap() ); + packetRemapInv.put( ProtocolConstants.MINECRAFT_SNAPSHOT, new TIntIntHashMap() ); + } + + public final DefinedPacket createPacket(int id, int protocol) + { + TIntIntMap remap = packetRemap.get( protocol ); + if ( remap != null ) + { + if ( !remap.containsKey( id ) ) + { + throw new BadPacketException( "No packet with id " + id ); + } + id = remap.get( id ); + } if ( id > MAX_PACKET_ID ) { throw new BadPacketException( "Packet with id " + id + " outside of range " ); @@ -137,6 +160,11 @@ public enum Protocol } protected final void registerPacket(int id, Class packetClass) + { + registerPacket( id, id, packetClass ); + } + + protected final void registerPacket(int id, int newId, Class packetClass) { try { @@ -147,6 +175,11 @@ public enum Protocol } packetClasses[id] = packetClass; packetMap.put( packetClass, id ); + + packetRemap.get( ProtocolConstants.MINECRAFT_1_8 ).put( id, id ); + packetRemapInv.get( ProtocolConstants.MINECRAFT_1_8 ).put(id, id); + packetRemap.get( ProtocolConstants.MINECRAFT_SNAPSHOT ).put( newId, id ); + packetRemapInv.get( ProtocolConstants.MINECRAFT_SNAPSHOT ).put( id, newId ); } protected final void unregisterPacket(int id) @@ -156,11 +189,17 @@ public enum Protocol packetConstructors[id] = null; } - final int getId(Class packet) + final int getId(Class packet, int protocol) { - Preconditions.checkArgument( packetMap.containsKey( packet ), "Cannot get ID for packet " + packet ); + Preconditions.checkArgument(packetMap.containsKey(packet), "Cannot get ID for packet " + packet); - return packetMap.get( packet ); + int id = packetMap.get( packet ); + TIntIntMap remap = packetRemapInv.get( protocol ); + if ( remap != null ) + { + return remap.get( id ); + } + return 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 9a300e08..2507170e 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 @@ -1,9 +1,16 @@ package net.md_5.bungee.protocol; +import java.util.Arrays; +import java.util.List; + public class ProtocolConstants { public static final int MINECRAFT_1_8 = 47; - public static final int MINECRAFT_SNAPSHOT = 54; + public static final int MINECRAFT_SNAPSHOT = 57; + public static final List SUPPORTED_VERSIONS = Arrays.asList( + "1.8.X", + "15w33c" + ); public enum Direction { 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 c7a6b92d..e4d87970 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 @@ -18,19 +18,24 @@ public class ClientSettings extends DefinedPacket private String locale; private byte viewDistance; - private byte chatFlags; + private int chatFlags; private boolean chatColours; private byte difficulty; private byte skinParts; + private int mainHand; @Override public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) { locale = readString( buf ); viewDistance = buf.readByte(); - chatFlags = buf.readByte(); + chatFlags = protocolVersion >= ProtocolConstants.MINECRAFT_SNAPSHOT ? DefinedPacket.readVarInt( buf ) : buf.readUnsignedByte(); chatColours = buf.readBoolean(); skinParts = buf.readByte(); + if ( protocolVersion >= ProtocolConstants.MINECRAFT_SNAPSHOT ) + { + mainHand = DefinedPacket.readVarInt( buf ); + } } @Override @@ -38,9 +43,19 @@ public class ClientSettings extends DefinedPacket { writeString( locale, buf ); buf.writeByte( viewDistance ); - buf.writeByte( chatFlags ); + if ( protocolVersion >= ProtocolConstants.MINECRAFT_SNAPSHOT ) + { + DefinedPacket.writeVarInt( chatFlags, buf ); + } else + { + buf.writeByte( chatFlags ); + } buf.writeBoolean( chatColours ); buf.writeByte( skinParts ); + if ( protocolVersion >= ProtocolConstants.MINECRAFT_SNAPSHOT ) + { + DefinedPacket.writeVarInt(mainHand, buf); + } } @Override 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 9bbeb2b6..176c71cf 100644 --- a/proxy/src/main/java/net/md_5/bungee/BungeeCord.java +++ b/proxy/src/main/java/net/md_5/bungee/BungeeCord.java @@ -1,6 +1,7 @@ package net.md_5.bungee; import com.google.common.base.Charsets; +import com.google.common.base.Joiner; import com.google.common.base.Preconditions; import com.google.common.base.Predicate; import com.google.common.collect.Iterables; @@ -575,7 +576,7 @@ public class BungeeCord extends ProxyServer @Override public String getGameVersion() { - return "1.8"; + return Joiner.on(", ").join(ProtocolConstants.SUPPORTED_VERSIONS); } @Override 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 d100591b..9dad21f3 100644 --- a/proxy/src/main/java/net/md_5/bungee/ServerConnector.java +++ b/proxy/src/main/java/net/md_5/bungee/ServerConnector.java @@ -4,6 +4,8 @@ import com.google.common.base.Objects; import com.google.common.base.Preconditions; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; + +import java.util.List; import java.util.Queue; import java.util.Set; import lombok.Getter; @@ -255,12 +257,24 @@ public class ServerConnector extends PacketHandler @Override public void handle(Kick kick) throws Exception { - ServerInfo def = bungee.getServerInfo( user.getPendingConnection().getListener().getFallbackServer() ); + user.setLastServerJoined(user.getLastServerJoined() + 1); + String serverName = ""; + List servers = user.getPendingConnection().getListener().getServerPriority(); + if ( user.getLastServerJoined() < servers.size() ) { + serverName = servers.get( user.getLastServerJoined() ); + } + ServerInfo def = ProxyServer.getInstance().getServers().get( serverName ); if ( Objects.equal( target, def ) ) { def = null; } - ServerKickEvent event = bungee.getPluginManager().callEvent( new ServerKickEvent( user, target, ComponentSerializer.parse( kick.getMessage() ), def, ServerKickEvent.State.CONNECTING ) ); + ServerKickEvent event = new ServerKickEvent(user, target, ComponentSerializer.parse(kick.getMessage()), def, ServerKickEvent.State.CONNECTING); + if ( event.getKickReason().toLowerCase().contains( "outdated" ) && def != null ) + { + // Pre cancel the event if we are going to try another server + event.setCancelled( true ); + } + bungee.getPluginManager().callEvent( event ); if ( event.isCancelled() && event.getCancelServer() != null ) { user.connect( event.getCancelServer() ); @@ -314,11 +328,6 @@ public class ServerConnector extends PacketHandler if ( pluginMessage.getTag().equals( ForgeConstants.FML_HANDSHAKE_TAG ) || pluginMessage.getTag().equals( ForgeConstants.FORGE_REGISTER ) ) { this.handshakeHandler.handle( pluginMessage ); - if ( user.getForgeClientHandler().checkUserOutdated() ) - { - ch.close(); - user.getPendingConnects().remove( target ); - } // 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 e4d15153..d7e4a276 100644 --- a/proxy/src/main/java/net/md_5/bungee/UserConnection.java +++ b/proxy/src/main/java/net/md_5/bungee/UserConnection.java @@ -14,6 +14,7 @@ import java.net.InetSocketAddress; import java.util.Collection; import java.util.Collections; import java.util.HashSet; +import java.util.List; import java.util.Locale; import java.util.Map; import java.util.UUID; @@ -55,6 +56,8 @@ import net.md_5.bungee.protocol.packet.Kick; import net.md_5.bungee.protocol.packet.PlayerListHeaderFooter; import net.md_5.bungee.protocol.packet.PluginMessage; import net.md_5.bungee.protocol.packet.SetCompression; +import net.md_5.bungee.tab.Global; +import net.md_5.bungee.tab.GlobalPing; import net.md_5.bungee.tab.ServerUnique; import net.md_5.bungee.tab.TabList; import net.md_5.bungee.util.CaseInsensitiveSet; @@ -102,6 +105,10 @@ public final class UserConnection implements ProxiedPlayer private int gamemode; @Getter private int compressionThreshold = -1; + // Used for trying multiple servers in order + @Getter + @Setter + private int lastServerJoined = 0; /*========================================================================*/ private final Collection groups = new CaseInsensitiveSet(); private final Collection permissions = new CaseInsensitiveSet(); @@ -145,20 +152,18 @@ public final class UserConnection implements ProxiedPlayer this.displayName = name; - // Blame Mojang for this one - /*switch ( getPendingConnection().getListener().getTabListType() ) - { - case "GLOBAL": - tabListHandler = new Global( this ); - break; - case "SERVER": - tabListHandler = new ServerUnique( this ); - break; - default: - tabListHandler = new GlobalPing( this ); - break; - }*/ - tabListHandler = new ServerUnique( this ); + switch ( getPendingConnection().getListener().getTabListType() ) + { + case "GLOBAL": + tabListHandler = new Global( this ); + break; + case "SERVER": + tabListHandler = new ServerUnique( this ); + break; + default: + tabListHandler = new GlobalPing( this ); + break; + } Collection g = bungee.getConfigurationAdapter().getGroups( name ); g.addAll( bungee.getConfigurationAdapter().getGroups( getUniqueId().toString() ) ); @@ -187,7 +192,7 @@ public final class UserConnection implements ProxiedPlayer @Override public void setDisplayName(String name) { - Preconditions.checkNotNull( name, "displayName" ); + Preconditions.checkNotNull(name, "displayName"); Preconditions.checkArgument( name.length() <= 16, "Display name cannot be longer than 16 characters" ); displayName = name; } @@ -267,9 +272,16 @@ public final class UserConnection implements ProxiedPlayer if ( !future.isSuccess() ) { future.channel().close(); - pendingConnects.remove( target ); + pendingConnects.remove(target); - ServerInfo def = ProxyServer.getInstance().getServers().get( getPendingConnection().getListener().getFallbackServer() ); + lastServerJoined++; + String serverName = ""; + List servers = getPendingConnection().getListener().getServerPriority(); + if ( lastServerJoined < servers.size() ) { + serverName = servers.get( lastServerJoined ); + } + + ServerInfo def = ProxyServer.getInstance().getServers().get( serverName ); if ( retry && target != def && ( getServer() == null || def != getServer().getInfo() ) ) { sendMessage( bungee.getTranslation( "fallback_lobby" ) ); @@ -281,6 +293,8 @@ public final class UserConnection implements ProxiedPlayer { sendMessage( bungee.getTranslation( "fallback_kick", future.cause().getClass().getName() ) ); } + } else { + lastServerJoined = 0; } } }; 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 a1097e40..41952eb7 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 @@ -27,6 +27,8 @@ public abstract class EntityMap { case ProtocolConstants.MINECRAFT_1_8: return EntityMap_1_8.INSTANCE; + case ProtocolConstants.MINECRAFT_SNAPSHOT: + return EntityMap_1_SNAPSHOT.INSTANCE; } throw new RuntimeException( "Version " + version + " has no entity map" ); } diff --git a/proxy/src/main/java/net/md_5/bungee/entitymap/EntityMap_1_8.java b/proxy/src/main/java/net/md_5/bungee/entitymap/EntityMap_1_8.java index b713d4dd..fb410644 100644 --- a/proxy/src/main/java/net/md_5/bungee/entitymap/EntityMap_1_8.java +++ b/proxy/src/main/java/net/md_5/bungee/entitymap/EntityMap_1_8.java @@ -97,28 +97,12 @@ class EntityMap_1_8 extends EntityMap 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 ); - } } } } else if ( packetId == 0x0C /* Spawn Player */ ) diff --git a/proxy/src/main/java/net/md_5/bungee/entitymap/EntityMap_SNAPSHOT.java b/proxy/src/main/java/net/md_5/bungee/entitymap/EntityMap_SNAPSHOT.java new file mode 100644 index 00000000..04ee1407 --- /dev/null +++ b/proxy/src/main/java/net/md_5/bungee/entitymap/EntityMap_SNAPSHOT.java @@ -0,0 +1,181 @@ +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.api.connection.ProxiedPlayer; +import net.md_5.bungee.protocol.DefinedPacket; +import net.md_5.bungee.protocol.ProtocolConstants; + +import java.util.UUID; + +class EntityMap_SNAPSHOT extends EntityMap +{ + static final EntityMap_SNAPSHOT INSTANCE = new EntityMap_SNAPSHOT(); + + EntityMap_SNAPSHOT() + { + addRewrite( 0x04, ProtocolConstants.Direction.TO_CLIENT, true ); // Entity Equipment + addRewrite( 0x0A, ProtocolConstants.Direction.TO_CLIENT, true ); // 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, true ); // 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, true ); // Entity Velocity + addRewrite( 0x14, ProtocolConstants.Direction.TO_CLIENT, true ); // Entity + addRewrite( 0x15, ProtocolConstants.Direction.TO_CLIENT, true ); // Entity Relative Move + addRewrite( 0x16, ProtocolConstants.Direction.TO_CLIENT, true ); // Entity Look + addRewrite( 0x17, ProtocolConstants.Direction.TO_CLIENT, true ); // Entity Look and Relative Move + addRewrite( 0x18, ProtocolConstants.Direction.TO_CLIENT, true ); // Entity Teleport + addRewrite( 0x19, ProtocolConstants.Direction.TO_CLIENT, true ); // 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, true ); // Entity Metadata + addRewrite( 0x1D, ProtocolConstants.Direction.TO_CLIENT, true ); // Entity Effect + addRewrite( 0x1E, ProtocolConstants.Direction.TO_CLIENT, true ); // Remove Entity Effect + addRewrite( 0x20, ProtocolConstants.Direction.TO_CLIENT, true ); // Entity Properties + addRewrite( 0x25, ProtocolConstants.Direction.TO_CLIENT, true ); // Block Break Animation + addRewrite( 0x2C, ProtocolConstants.Direction.TO_CLIENT, true ); // Spawn Global Entity + addRewrite( 0x43, ProtocolConstants.Direction.TO_CLIENT, true ); // Camera + addRewrite( 0x49, ProtocolConstants.Direction.TO_CLIENT, true ); // Update Entity NBT + + addRewrite( 0x02, ProtocolConstants.Direction.TO_SERVER, true ); // Use Entity + addRewrite( 0x0C, ProtocolConstants.Direction.TO_SERVER, true ); // Entity Action + } + + @Override + @SuppressFBWarnings("DLS_DEAD_LOCAL_STORE") + 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 */ ) + { + DefinedPacket.readVarInt( packet ); + rewriteVarInt( packet, oldId, newId, packet.readerIndex() ); + } else if ( packetId == 0x1B /* Attach Entity */ ) + { + rewriteInt( packet, oldId, newId, readerIndex + packetIdLength + 4 ); + } else if ( packetId == 0x13 /* Destroy Entities */ ) + { + int count = DefinedPacket.readVarInt( packet ); + int[] ids = new int[ count ]; + for ( int i = 0; i < count; i++ ) + { + ids[ i ] = DefinedPacket.readVarInt( packet ); + } + packet.readerIndex( readerIndex + packetIdLength ); + packet.writerIndex( readerIndex + packetIdLength ); + DefinedPacket.writeVarInt( count, packet ); + for ( int id : ids ) + { + if ( id == oldId ) + { + id = newId; + } else if ( id == newId ) + { + id = oldId; + } + DefinedPacket.writeVarInt( id, packet ); + } + } 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 ); + } + } + } + } else if ( packetId == 0x0C /* Spawn Player */ ) + { + DefinedPacket.readVarInt( packet ); // Entity ID + int idLength = packet.readerIndex() - readerIndex - packetIdLength; + UUID uuid = DefinedPacket.readUUID( packet ); + ProxiedPlayer player; + if ( ( player = BungeeCord.getInstance().getPlayerByOfflineUUID( uuid ) ) != null ) + { + int previous = packet.writerIndex(); + packet.readerIndex( readerIndex ); + packet.writerIndex( readerIndex + packetIdLength + idLength ); + DefinedPacket.writeUUID( player.getUniqueId(), packet ); + packet.writerIndex( previous ); + } + } else if ( packetId == 0x42 /* Combat Event */ ) + { + int event = packet.readUnsignedByte(); + if ( event == 1 /* End Combat*/ ) + { + DefinedPacket.readVarInt( packet ); + rewriteInt( packet, oldId, newId, packet.readerIndex() ); + } else if ( event == 2 /* Entity Dead */ ) + { + int position = packet.readerIndex(); + rewriteVarInt( packet, oldId, newId, packet.readerIndex() ); + packet.readerIndex( position ); + DefinedPacket.readVarInt( packet ); + rewriteInt( packet, oldId, newId, packet.readerIndex() ); + } + } + packet.readerIndex( readerIndex ); + } + + @Override + public void rewriteServerbound(ByteBuf packet, int oldId, int newId) + { + super.rewriteServerbound( packet, oldId, newId ); + //Special cases + int readerIndex = packet.readerIndex(); + int packetId = DefinedPacket.readVarInt( packet ); + int packetIdLength = packet.readerIndex() - readerIndex; + + if ( packetId == 0x19 /* Spectate */ && !BungeeCord.getInstance().getConfig().isIpForward() ) + { + UUID uuid = DefinedPacket.readUUID( packet ); + ProxiedPlayer player; + if ( ( player = BungeeCord.getInstance().getPlayer( uuid ) ) != null ) + { + int previous = packet.writerIndex(); + packet.readerIndex( readerIndex ); + packet.writerIndex( readerIndex + packetIdLength ); + DefinedPacket.writeUUID( ( (UserConnection) player ).getPendingConnection().getOfflineId(), packet ); + packet.writerIndex( previous ); + } + } + packet.readerIndex( readerIndex ); + } +} 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 3281ee98..314fd436 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 @@ -21,10 +21,6 @@ public class ForgeClientHandler @NonNull private final UserConnection con; - @Getter - @Setter(AccessLevel.PACKAGE) - private boolean forgeOutdated = false; - /** * The users' mod list. */ @@ -160,28 +156,4 @@ public class ForgeClientHandler { return fmlTokenInHandshake || clientModList != null; } - - /** - * 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 ) - { - if ( con.isDimensionChange() ) - { - con.disconnect( BungeeCord.getInstance().getTranslation( "connect_kick_outdated_forge" ) ); - } else - { - con.sendMessage( BungeeCord.getInstance().getTranslation( "connect_kick_outdated_forge" ) ); - } - } - - return forgeOutdated; - } } 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 79a6f963..f1e2376d 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 @@ -86,17 +86,6 @@ enum ForgeClientHandshakeState implements IForgeClientPacketHandler clientModList = ForgeUtils.readModList( message ); con.getForgeClientHandler().setClientModList( clientModList ); - - // 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 ); - } } return WAITINGSERVERDATA;