diff --git a/.travis.yml b/.travis.yml
index 1cd525b712..7f19acceeb 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,8 +1,40 @@
sudo: false
language: java
jdk:
- - openjdk7
- - oraclejdk7
- oraclejdk8
+branches:
+ except:
+ - /^v[0-9]*/
notifications:
email: false
+ irc:
+ channels:
+ - "irc.spi.gt#hexagonmc"
+ use_notice: true
+ skip_join: true
+install:
+ - mvn install -DskipTests=true -Dmaven.javadoc.skip=true -Dbuild.number=$TRAVIS_BUILD_NUMBER -B -V
+after_success:
+ # CREATE GIT TAG
+ - git config --global user.email "builds@travis-ci.com"
+ - git config --global user.name "Travis CI"
+ - export GIT_TAG=v$TRAVIS_BUILD_NUMBER
+ - echo -n $GIT_TAG > VERSION
+ - git commit -m "Set build VERSION number" VERSION
+ - git tag $GIT_TAG -a -m "Generated tag from TravisCI build $TRAVIS_BUILD_NUMBER"
+ - git push --quiet https://$GITHUBKEY@github.com/dev-confidence/example-backend-api $GIT_TAG > /dev/null 2>&1
+deploy:
+ provider: releases
+ skip_cleanup: true
+ api_key:
+ secure: ljpg29wmo0yPs+qXBVj1vHnY4WPXB1hNMDnHMxhXbPRhK5l9kCqJWy4YjJ6BbEb4keU5dMmt+cyB+Njr3IomJMoupVu0Osut/SNz4g0UZFTYYJQjvrurdmGxoh9E7xmc6Pcly+Pw99RSpqK+yD8SDDepTleHDv/8pC0d4Z5NZIJ9JJUeY2in1RXpStj7rJtmSN5XWFpWBGpHElFQqaSDfh62zn3bvb7J9oVA+NtBDXgpY1Km1Q76Evt4PuijOgdWx4rcNpi7UOd6XurkYuo4/igBEUE8HQSEIqgC0jxJg0gxtLbymPvW4sPXmEPhZwIUvoYFjX0DvlIqU8hbr/2CPtcHiKqnqTU92wgFFnf3Xvn2mdoCrgHDOcSA2JWsR70077bPzv+llNHN17mDlGE7vIiv54jNBkJpem8OBgDNIU2lDnhwZQr3ifZJ0ydhdhkYK7Kp1lAZtEZwbqs6cetlwLiuBH6wd3dErBduPQNLnl22qdhQQJFBXPkj+vHBAt9uSB3irWWME0XsR6G9OpzDYoO64vkkHnz1k7VK37ud2pe7yKYuUr+MUbyBnzycbKOhYRufPkMv8RJIbRH6lChRrZOamqbZTa1FFYsemgcJ9NG990tE0zJHw0G3vU+emxPY35UPIMZrSbzQ8mCOlwKfhAtubZRNe+V0ohJFvVx/dhI=
+ file:
+ - bootstrap/target/BungeeCord.jar
+ - module/*/target/*.jar
+ file_glob: true
+ on:
+ branch: master
+cache:
+ directories:
+ - $HOME/.m2
+
diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md
new file mode 100644
index 0000000000..c175fce1b6
--- /dev/null
+++ b/ISSUE_TEMPLATE.md
@@ -0,0 +1,13 @@
+### What Hexacord version are you using? Post the output of /bungee
+
+
+### Are you using Bungee plugins? If yes, please list all of them + versionnumber
+
+
+### How can we reproduce the error/bug?
+
+
+### Is an error message (bungee/spigot/client)? If yes, use pastebin.com and share the link.
+
+
+### In addidtion to that, please explain your issue as detailed as possible.
diff --git a/README.md b/README.md
index 331a448902..cd69390b53 100644
--- a/README.md
+++ b/README.md
@@ -1,20 +1,22 @@
-BungeeCord
+
+BungeeCord for 1.7/1.8/1.9/1.10/1.11/1.12
==========
-Layer 7 proxy designed to link Minecraft servers.
---------------------------------------------------
+[![Build Status](https://travis-ci.org/HexagonMC/BungeeCord.svg?branch=master)](https://travis-ci.org/HexagonMC/BungeeCord)
+
+This is a fork of md_5's BungeeCord
+https://www.spigotmc.org/threads/1-8-1-9-bungeecord.392/
-BungeeCord is a sophisticated proxy and API designed mainly to teleport players between multiple Minecraft servers. It is the latest incarnation of similar software written by the author from 2011-present.
+This version reimplements Minecraft 1.7.10 and basic 1.7.10 Forge support.
-Information
------------
-BungeeCord is maintained by [SpigotMC](https://www.spigotmc.org/) and has its own [discussion thread](https://www.spigotmc.org/go/bungeecord) with plenty of helpful information and links.
+Since release 134+, SpongePls is no longer needed when using Sponge-servers within your network!
-Source
-------
-Source code is currently available on [GitHub](https://www.spigotmc.org/go/bungeecord-git).
+IMPORTANT: We WON'T fix any 1.7 bugs.
+This fork is designed for keeping your old servers in your network, until your modspacks are available for 1.10.2/1.11.2 or higher.
+Most of them are, so get rid of 1.7 fast and move to 1.10.2/1.11.2 modpacks asap.
-Binaries
---------
-Precompiled binaries are available for end users on [Jenkins](https://www.spigotmc.org/go/bungeecord-dl).
+This version is maintained by https://hexagonmc.eu
-(c) 2012-2017 SpigotMC Pty. Ltd.
+###Releases can be downloaded here: [Releases](https://github.com/HexagonMC/BungeeCord/releases)
+```
+Modules are automatically downloaded from the releases page.
+```
diff --git a/api/src/main/java/net/md_5/bungee/api/ProxyConfig.java b/api/src/main/java/net/md_5/bungee/api/ProxyConfig.java
index edd82c1e0e..d44a356a00 100644
--- a/api/src/main/java/net/md_5/bungee/api/ProxyConfig.java
+++ b/api/src/main/java/net/md_5/bungee/api/ProxyConfig.java
@@ -79,4 +79,14 @@ public interface ProxyConfig
* The favicon used for the server ping list.
*/
Favicon getFaviconObject();
+
+ /**
+ * The server name for the server ping list.
+ */
+ String getCustomServerName();
+
+ /**
+ * Whether the server should handle packets before the player has connected to a server
+ */
+ boolean getAlwaysHandlePackets();
}
diff --git a/bootstrap/pom.xml b/bootstrap/pom.xml
index 9b5c98f7d5..0de8409018 100644
--- a/bootstrap/pom.xml
+++ b/bootstrap/pom.xml
@@ -52,7 +52,7 @@
net.md_5.bungee.Bootstrap
${describe}
- ${maven.build.timestamp}
+ ${build.number}
diff --git a/bootstrap/src/main/java/net/md_5/bungee/BungeeCordLauncher.java b/bootstrap/src/main/java/net/md_5/bungee/BungeeCordLauncher.java
index 3c1bbe9360..109a61c5b9 100644
--- a/bootstrap/src/main/java/net/md_5/bungee/BungeeCordLauncher.java
+++ b/bootstrap/src/main/java/net/md_5/bungee/BungeeCordLauncher.java
@@ -1,51 +1,107 @@
package net.md_5.bungee;
+
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.net.URLConnection;
import java.security.Security;
-import java.text.SimpleDateFormat;
import java.util.Arrays;
-import java.util.Calendar;
-import java.util.Date;
import java.util.concurrent.TimeUnit;
+
+import com.google.gson.JsonIOException;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import com.google.gson.JsonSyntaxException;
+
import joptsimple.OptionParser;
import joptsimple.OptionSet;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.command.ConsoleCommandSender;
+
public class BungeeCordLauncher
{
-
public static void main(String[] args) throws Exception
{
Security.setProperty( "networkaddress.cache.ttl", "30" );
Security.setProperty( "networkaddress.cache.negative.ttl", "10" );
-
+
OptionParser parser = new OptionParser();
parser.allowsUnrecognizedOptions();
- parser.acceptsAll( Arrays.asList( "v", "version" ) );
+ parser.acceptsAll( Arrays.asList( "v", "version") );
parser.acceptsAll( Arrays.asList( "noconsole" ) );
OptionSet options = parser.parse( args );
- if ( options.has( "version" ) )
+ if ( options.has("version") )
{
- System.out.println( Bootstrap.class.getPackage().getImplementationVersion() );
+ System.out.println(Bootstrap.class.getPackage().getImplementationVersion());
return;
}
- if ( BungeeCord.class.getPackage().getSpecificationVersion() != null && System.getProperty( "IReallyKnowWhatIAmDoingISwear" ) == null )
+ if ( BungeeCord.class.getPackage().getSpecificationVersion() != null && System.getProperty( "IReallyKnowWhatIAmDoingISwear" ) == null)
{
- Date buildDate = new SimpleDateFormat( "yyyyMMdd" ).parse( BungeeCord.class.getPackage().getSpecificationVersion() );
-
- Calendar deadline = Calendar.getInstance();
- deadline.add( Calendar.WEEK_OF_YEAR, -4 );
- if ( buildDate.before( deadline.getTime() ) )
+ String version = BungeeCord.class.getPackage().getSpecificationVersion();
+
+ if ( version.equalsIgnoreCase("unknown") )
+ {
+ System.err.println( "*** You are using a self compiled version ***" );
+ System.err.println( "*** Please make sure your server is up to date ***" );
+ System.err.println( "*** Using current version without warranty ***" );
+ System.err.println( "*** Server will start in 2 seconds ***" );
+ Thread.sleep( TimeUnit.SECONDS.toMillis( 2 ) );
+ } else
{
- System.err.println( "*** Warning, this build is outdated ***" );
- System.err.println( "*** Please download a new build from http://ci.md-5.net/job/BungeeCord ***" );
- System.err.println( "*** You will get NO support regarding this build ***" );
- System.err.println( "*** Server will start in 10 seconds ***" );
- Thread.sleep( TimeUnit.SECONDS.toMillis( 10 ) );
+ int currentVersion = Integer.parseInt( version );
+
+ try
+ {
+ URL api = new URL( "https://api.github.com/repos/HexagonMC/BungeeCord/releases/latest" );
+ URLConnection con = api.openConnection();
+ // 15 second timeout at various stages
+ con.setConnectTimeout( 15000 );
+ con.setReadTimeout( 15000 );
+
+ String tagName = null;
+
+ try
+ {
+ JsonObject json = new JsonParser().parse( new InputStreamReader( con.getInputStream() ) ).getAsJsonObject();
+ tagName = json.get( "tag_name" ).getAsString();
+
+ int latestVersion = Integer.parseInt( tagName.substring( 1, tagName.length() ) );
+
+ if ( latestVersion > currentVersion )
+ {
+ System.err.println("*** Warning, this build is outdated ***");
+ System.err.println("*** Please download a new build from https://github.com/HexagonMC/BungeeCord/releases ***");
+ System.err.println("*** You will get NO support regarding this build ***");
+ System.err.println("*** Server will start in 10 seconds ***");
+ Thread.sleep(TimeUnit.SECONDS.toMillis(10));
+ }
+ }
+ catch ( JsonIOException e )
+ {
+ throw new IOException(e);
+ }
+ catch ( JsonSyntaxException e )
+ {
+ throw new IOException( e );
+ }
+ catch( NumberFormatException e )
+ {
+ throw new IOException( e );
+ }
+ }
+ catch ( IOException e )
+ {
+ System.err.println( "*** Can not test if up to date ***" );
+ System.err.println( "*** Using current version without warranty ***" );
+ System.err.println( "*** Server will start in 2 seconds ***" );
+ Thread.sleep( TimeUnit.SECONDS.toMillis( 2 ) );
+ }
}
}
@@ -59,7 +115,7 @@ public static void main(String[] args) throws Exception
String line;
while ( bungee.isRunning && ( line = bungee.getConsoleReader().readLine( ">" ) ) != null )
{
- if ( !bungee.getPluginManager().dispatchCommand( ConsoleCommandSender.getInstance(), line ) )
+ if ( !bungee.getPluginManager().dispatchCommand(ConsoleCommandSender.getInstance(), line ) )
{
bungee.getConsole().sendMessage( ChatColor.RED + "Command not found" );
}
diff --git a/pom.xml b/pom.xml
index 714d421d65..87bf735183 100644
--- a/pom.xml
+++ b/pom.xml
@@ -16,7 +16,7 @@
BungeeCord-Parent
Parent project for all BungeeCord modules.
- https://github.com/SpigotMC/BungeeCord
+ https://github.com/HexagonMC/BungeeCord
2012
SpigotMC
@@ -34,6 +34,12 @@
md_5
+
+ Zartec
+
+
+ ghac
+
@@ -51,17 +57,17 @@
- scm:git:git@github.com:SpigotMC/BungeeCord.git
- scm:git:git@github.com:SpigotMC/BungeeCord.git
- git@github.com:SpigotMC/BungeeCord.git
+ scm:git:git@github.com:HexagonMC/BungeeCord.git
+ scm:git:git@github.com:HexagonMC/BungeeCord.git
+ git@github.com:HexagonMC/BungeeCord.git
GitHub
- https://github.com/SpigotMC/BungeeCord/issues
+ https://github.com/HexagonMC/BungeeCord/issues
- jenkins
- http://ci.md-5.net/job/BungeeCord
+ travis-ci
+ https://travis-ci.org/HexagonMC/BungeeCord
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 10e16d794e..543487229c 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
@@ -1,6 +1,7 @@
package net.md_5.bungee.protocol;
import com.google.common.base.Charsets;
+import com.google.common.base.Preconditions;
import io.netty.buffer.ByteBuf;
import java.util.ArrayList;
import java.util.List;
@@ -72,6 +73,36 @@ public static byte[] readArray(ByteBuf buf, int limit)
buf.readBytes( ret );
return ret;
}
+
+ public static void writeArrayLegacy(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[] readArrayLegacy(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;
+ }
public static void writeStringArray(List s, ByteBuf buf)
{
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 e7cb380342..9c5d4da17f 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
@@ -34,7 +34,7 @@ protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) t
if ( in.isReadable() )
{
- throw new BadPacketException( "Did not read all bytes from packet " + packet.getClass() + " " + packetId + " Protocol " + protocol + " Direction " + prot );
+ throw new BadPacketException( "Did not read all bytes from packet " + packet.getClass() + " " + packetId + " Protocol " + protocol + " Direction " + prot.getDirection().name() );
}
} else
{
diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/MinecraftInput.java b/protocol/src/main/java/net/md_5/bungee/protocol/MinecraftInput.java
new file mode 100644
index 0000000000..ef2e269556
--- /dev/null
+++ b/protocol/src/main/java/net/md_5/bungee/protocol/MinecraftInput.java
@@ -0,0 +1,38 @@
+package net.md_5.bungee.protocol;
+
+import io.netty.buffer.ByteBuf;
+import lombok.RequiredArgsConstructor;
+
+@RequiredArgsConstructor
+public class MinecraftInput
+{
+
+ private final ByteBuf buf;
+
+ public byte readByte()
+ {
+ return buf.readByte();
+ }
+
+ public short readUnsignedByte()
+ {
+ return buf.readUnsignedByte();
+ }
+
+ public int readInt()
+ {
+ return buf.readInt();
+ }
+
+ public String readString()
+ {
+ short len = buf.readShort();
+ char[] c = new char[ len ];
+ for ( int i = 0; i < c.length; i++ )
+ {
+ c[i] = buf.readChar();
+ }
+
+ return new String( c );
+ }
+}
diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/MinecraftOutput.java b/protocol/src/main/java/net/md_5/bungee/protocol/MinecraftOutput.java
new file mode 100644
index 0000000000..94f6613d5d
--- /dev/null
+++ b/protocol/src/main/java/net/md_5/bungee/protocol/MinecraftOutput.java
@@ -0,0 +1,56 @@
+package net.md_5.bungee.protocol;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import java.nio.charset.Charset;
+import java.util.Arrays;
+
+public class MinecraftOutput
+{
+
+ private final ByteBuf buf;
+
+ public MinecraftOutput()
+ {
+ buf = Unpooled.buffer();
+ }
+
+ public byte[] toArray()
+ {
+ if ( buf.hasArray() )
+ {
+ return Arrays.copyOfRange( buf.array(), buf.arrayOffset(), buf.arrayOffset() + buf.writerIndex() );
+ } else
+ {
+ byte[] b = new byte[ buf.writerIndex() ];
+ buf.readBytes( b );
+ return b;
+ }
+ }
+
+ public MinecraftOutput writeByte(byte b)
+ {
+ buf.writeByte( b );
+ return this;
+ }
+
+ public void writeInt(int i)
+ {
+ buf.writeInt( i );
+ }
+
+ public void writeString(String s)
+ {
+ char[] cc = s.toCharArray();
+ buf.writeShort( cc.length );
+ for ( char c : cc )
+ {
+ buf.writeChar( c );
+ }
+ }
+
+ public void writeStringUTF8WithoutLengthHeaderBecauseDinnerboneStuffedUpTheMCBrandPacket(String s)
+ {
+ buf.writeBytes( s.getBytes( Charset.forName( "UTF-8" ) ) );
+ }
+}
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 f06aa95ab9..90b3ff13b9 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
@@ -154,6 +154,12 @@ public enum Protocol
map( ProtocolConstants.MINECRAFT_1_12, 0x49 ),
map( ProtocolConstants.MINECRAFT_1_12_1, 0x4A )
);
+ TO_CLIENT.registerPacket(
+ SetCompression.class,
+ map( ProtocolConstants.MINECRAFT_1_7_2, 0x46 , false ),
+ map( ProtocolConstants.MINECRAFT_1_7_6, 0x46 , false ),
+ map( ProtocolConstants.MINECRAFT_1_8, 0x46 , false )
+ );
TO_SERVER.registerPacket(
KeepAlive.class,
@@ -300,10 +306,14 @@ private static class ProtocolData {
private static class ProtocolMapping {
private final int protocolVersion;
private final int packetID;
+ private final boolean inherit;
}
// Helper method
private static ProtocolMapping map(int protocol, int id) {
- return new ProtocolMapping(protocol, id);
+ return map(protocol, id, true);
+ }
+ private static ProtocolMapping map(int protocol, int id, boolean inherit) {
+ return new ProtocolMapping(protocol, id, inherit);
}
@RequiredArgsConstructor
@@ -320,7 +330,11 @@ public static class DirectionData
}
private final TIntObjectMap> linkedProtocols = new TIntObjectHashMap<>();
{
+ linkedProtocols.put( ProtocolConstants.MINECRAFT_1_7_2, Arrays.asList(
+ ProtocolConstants.MINECRAFT_1_7_6
+ ));
linkedProtocols.put( ProtocolConstants.MINECRAFT_1_8, Arrays.asList(
+ ProtocolConstants.MINECRAFT_1_7_2,
ProtocolConstants.MINECRAFT_1_9,
ProtocolConstants.MINECRAFT_1_12
) );
@@ -388,20 +402,23 @@ protected final void registerPacket(Class extends DefinedPacket> packetClass,
data.packetMap.put( packetClass, mapping.packetID );
data.packetConstructors[mapping.packetID] = constructor;
- List links = linkedProtocols.get( mapping.protocolVersion );
- if ( links != null )
+ if (mapping.inherit)
{
- links: for ( int link : links )
+ List links = linkedProtocols.get( mapping.protocolVersion );
+ if ( links != null )
{
- // Check for manual mappings
- for ( ProtocolMapping m : mappings )
+ links: for ( int link : links )
{
- if ( m == mapping ) continue;
- if ( m.protocolVersion == link ) continue links;
- List innerLinks = linkedProtocols.get( m.protocolVersion );
- if ( innerLinks != null && innerLinks.contains( link ) ) continue links;
+ // Check for manual mappings
+ for ( ProtocolMapping m : mappings )
+ {
+ if ( m == mapping ) continue;
+ if ( m.protocolVersion == link ) continue links;
+ List innerLinks = linkedProtocols.get( m.protocolVersion );
+ if ( innerLinks != null && innerLinks.contains( link ) ) continue links;
+ }
+ registerPacket( packetClass, map( link, mapping.packetID ) );
}
- registerPacket( packetClass, map( link, mapping.packetID ) );
}
}
}
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 ac9adf3323..4ed107f5c9 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
@@ -5,7 +5,8 @@
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;
@@ -18,13 +19,18 @@ public class ProtocolConstants
public static final int MINECRAFT_1_12_1 = 338;
public static final int MINECRAFT_1_12_2 = 340;
public static final List SUPPORTED_VERSIONS = Arrays.asList(
+ "1.7.x",
"1.8.x",
"1.9.x",
"1.10.x",
"1.11.x",
"1.12.x"
);
- public static final List SUPPORTED_VERSION_IDS = Arrays.asList( ProtocolConstants.MINECRAFT_1_8,
+
+ public static final List SUPPORTED_VERSION_IDS = Arrays.asList(
+ ProtocolConstants.MINECRAFT_1_7_2,
+ ProtocolConstants.MINECRAFT_1_7_6,
+ ProtocolConstants.MINECRAFT_1_8,
ProtocolConstants.MINECRAFT_1_9,
ProtocolConstants.MINECRAFT_1_9_1,
ProtocolConstants.MINECRAFT_1_9_2,
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 95ad39b766..6144bd6195 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
@@ -28,7 +28,7 @@ public Chat(String message)
public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{
message = readString( buf );
- if ( direction == ProtocolConstants.Direction.TO_CLIENT )
+ if ( direction == ProtocolConstants.Direction.TO_CLIENT && protocolVersion >= ProtocolConstants.MINECRAFT_1_8 )
{
position = buf.readByte();
}
@@ -38,7 +38,7 @@ public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protoco
public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{
writeString( message, buf );
- if ( direction == ProtocolConstants.Direction.TO_CLIENT )
+ if ( direction == ProtocolConstants.Direction.TO_CLIENT && protocolVersion >= ProtocolConstants.MINECRAFT_1_8 )
{
buf.writeByte( position );
}
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 5c79727ca2..b17b6cebb1 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
@@ -31,6 +31,10 @@ public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protoco
viewDistance = buf.readByte();
chatFlags = protocolVersion >= ProtocolConstants.MINECRAFT_1_9 ? DefinedPacket.readVarInt( buf ) : buf.readUnsignedByte();
chatColours = buf.readBoolean();
+ if ( protocolVersion <= ProtocolConstants.MINECRAFT_1_7_6 )
+ {
+ difficulty = buf.readByte();
+ }
skinParts = buf.readByte();
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_9 )
{
@@ -51,6 +55,10 @@ public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protoc
buf.writeByte( chatFlags );
}
buf.writeBoolean( chatColours );
+ if ( protocolVersion <= ProtocolConstants.MINECRAFT_1_7_6 )
+ {
+ buf.writeByte( difficulty );
+ }
buf.writeByte( skinParts );
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_9 )
{
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 a29524ca81..3d1a3f7904 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
@@ -24,16 +24,30 @@ public class EncryptionRequest extends DefinedPacket
public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{
serverId = readString( buf );
- publicKey = readArray( buf );
- verifyToken = readArray( buf );
+ if ( protocolVersion < ProtocolConstants.MINECRAFT_1_8 )
+ {
+ publicKey = readArrayLegacy( buf );
+ verifyToken = readArrayLegacy( buf );
+ } else
+ {
+ publicKey = readArray( buf );
+ verifyToken = readArray( buf );
+ }
}
@Override
public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{
writeString( serverId, buf );
- writeArray( publicKey, buf );
- writeArray( verifyToken, buf );
+ if ( protocolVersion < ProtocolConstants.MINECRAFT_1_8 )
+ {
+ writeArrayLegacy( publicKey, buf, false );
+ writeArrayLegacy( verifyToken, buf, false );
+ } else
+ {
+ writeArray( publicKey, buf );
+ writeArray( verifyToken, buf );
+ }
}
@Override
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 06676e428e..067058499d 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
@@ -22,15 +22,29 @@ public class EncryptionResponse extends DefinedPacket
@Override
public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{
- sharedSecret = readArray( buf, 128 );
- verifyToken = readArray( buf, 128 );
+ if ( protocolVersion < ProtocolConstants.MINECRAFT_1_8 )
+ {
+ sharedSecret = readArrayLegacy( buf );
+ verifyToken = readArrayLegacy( buf );
+ } else
+ {
+ sharedSecret = readArray( buf, 128 );
+ verifyToken = readArray( buf, 128 );
+ }
}
@Override
public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{
- writeArray( sharedSecret, buf );
- writeArray( verifyToken, buf );
+ if ( protocolVersion < ProtocolConstants.MINECRAFT_1_8 )
+ {
+ writeArrayLegacy( sharedSecret, buf, false );
+ writeArrayLegacy( verifyToken, buf, false );
+ } else
+ {
+ writeArray( sharedSecret, buf );
+ writeArray( verifyToken, buf );
+ }
}
@Override
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 9df9ef567a..3a224a7496 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
@@ -21,7 +21,16 @@ public class KeepAlive extends DefinedPacket
@Override
public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{
- randomId = ( protocolVersion >= ProtocolConstants.MINECRAFT_1_12_2 ) ? buf.readLong() : readVarInt( buf );
+ if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_12_2 )
+ {
+ randomId = buf.readLong();
+ } else if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_8 )
+ {
+ randomId = readVarInt( buf );
+ } else
+ {
+ randomId = buf.readInt();
+ }
}
@Override
@@ -30,9 +39,12 @@ public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protoc
if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_12_2 )
{
buf.writeLong( randomId );
- } else
+ } else if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_8 )
{
writeVarInt( (int) randomId, buf );
+ } else
+ {
+ buf.writeInt( (int) randomId );
}
}
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 9983ef2e4d..e912882633 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
@@ -22,53 +22,63 @@ public class PlayerListItem extends DefinedPacket
@Override
public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{
- action = Action.values()[DefinedPacket.readVarInt( buf )];
- items = new Item[ DefinedPacket.readVarInt( buf ) ];
- for ( int i = 0; i < items.length; i++ )
+ if ( protocolVersion < ProtocolConstants.MINECRAFT_1_8 )
{
- Item item = items[i] = new Item();
- item.setUuid( DefinedPacket.readUUID( buf ) );
- switch ( action )
+ 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();
+ } else
+ {
+ action = Action.values()[ DefinedPacket.readVarInt( buf )];
+ items = new Item[ DefinedPacket.readVarInt( buf ) ];
+ for ( int i = 0; i < items.length; i++ )
{
- case ADD_PLAYER:
- item.username = DefinedPacket.readString( buf );
- item.properties = new String[ DefinedPacket.readVarInt( buf ) ][];
- for ( int j = 0; j < item.properties.length; j++ )
- {
- String name = DefinedPacket.readString( buf );
- String value = DefinedPacket.readString( buf );
- if ( buf.readBoolean() )
+ Item item = items[ i ] = new Item();
+ item.setUuid( DefinedPacket.readUUID( buf ) );
+ switch ( action )
+ {
+ case ADD_PLAYER:
+ item.username = DefinedPacket.readString( buf );
+ item.properties = new String[ DefinedPacket.readVarInt( buf ) ][];
+ for ( int j = 0; j < item.properties.length; j++ )
{
- item.properties[j] = new String[]
+ String name = DefinedPacket.readString( buf );
+ String value = DefinedPacket.readString( buf );
+ if ( buf.readBoolean() )
{
- name, value, DefinedPacket.readString( buf )
- };
- } else
- {
- item.properties[j] = new String[]
+ item.properties[j] = new String[]
+ {
+ name, value, DefinedPacket.readString( buf )
+ };
+ } else
{
- name, value
- };
+ item.properties[j] = new String[]
+ {
+ name, value
+ };
+ }
+ }
+ item.gamemode = DefinedPacket.readVarInt( buf );
+ item.ping = DefinedPacket.readVarInt( buf );
+ if ( buf.readBoolean() )
+ {
+ item.displayName = DefinedPacket.readString( buf );
}
- }
- item.gamemode = DefinedPacket.readVarInt( buf );
- item.ping = DefinedPacket.readVarInt( buf );
- if ( buf.readBoolean() )
- {
- item.displayName = DefinedPacket.readString( buf );
- }
- break;
- case UPDATE_GAMEMODE:
- item.gamemode = DefinedPacket.readVarInt( buf );
- break;
- case UPDATE_LATENCY:
- item.ping = DefinedPacket.readVarInt( buf );
- break;
- case UPDATE_DISPLAY_NAME:
- if ( buf.readBoolean() )
- {
- item.displayName = DefinedPacket.readString( buf );
- }
+ break;
+ case UPDATE_GAMEMODE:
+ item.gamemode = DefinedPacket.readVarInt( buf );
+ break;
+ case UPDATE_LATENCY:
+ item.ping = DefinedPacket.readVarInt( buf );
+ break;
+ case UPDATE_DISPLAY_NAME:
+ if ( buf.readBoolean() )
+ {
+ item.displayName = DefinedPacket.readString( buf );
+ }
+ }
}
}
}
@@ -76,50 +86,59 @@ public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protoco
@Override
public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{
- DefinedPacket.writeVarInt( action.ordinal(), buf );
- DefinedPacket.writeVarInt( items.length, buf );
- for ( Item item : items )
+ if ( protocolVersion < ProtocolConstants.MINECRAFT_1_8 )
+ {
+ 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 );
+ } else
{
- DefinedPacket.writeUUID( item.uuid, buf );
- switch ( action )
+ DefinedPacket.writeVarInt( action.ordinal(), buf );
+ DefinedPacket.writeVarInt( items.length, buf );
+ for ( Item item : items )
{
- case ADD_PLAYER:
- DefinedPacket.writeString( item.username, buf );
- DefinedPacket.writeVarInt( item.properties.length, buf );
- for ( String[] prop : item.properties )
- {
- DefinedPacket.writeString( prop[0], buf );
- DefinedPacket.writeString( prop[1], buf );
- if ( prop.length >= 3 )
+ DefinedPacket.writeUUID( item.uuid, buf );
+ switch ( action )
+ {
+ case ADD_PLAYER:
+ DefinedPacket.writeString( item.username, buf );
+ DefinedPacket.writeVarInt( item.properties.length, buf );
+ for ( String[] prop : item.properties )
{
- buf.writeBoolean( true );
- DefinedPacket.writeString( prop[2], buf );
- } else
+ DefinedPacket.writeString( prop[ 0], buf );
+ DefinedPacket.writeString( prop[ 1], buf );
+ if ( prop.length >= 3 )
+ {
+ buf.writeBoolean( true );
+ DefinedPacket.writeString( prop[ 2], buf );
+ } else
+ {
+ buf.writeBoolean( false );
+ }
+ }
+ DefinedPacket.writeVarInt( item.gamemode, buf );
+ DefinedPacket.writeVarInt( item.ping, buf );
+ buf.writeBoolean( item.displayName != null );
+ if ( item.displayName != null )
+ {
+ DefinedPacket.writeString( item.displayName, buf );
+ }
+ break;
+ case UPDATE_GAMEMODE:
+ DefinedPacket.writeVarInt( item.gamemode, buf );
+ break;
+ case UPDATE_LATENCY:
+ DefinedPacket.writeVarInt( item.ping, buf );
+ break;
+ case UPDATE_DISPLAY_NAME:
+ buf.writeBoolean( item.displayName != null );
+ if ( item.displayName != null )
{
- buf.writeBoolean( false );
+ DefinedPacket.writeString( item.displayName, buf );
}
- }
- DefinedPacket.writeVarInt( item.gamemode, buf );
- DefinedPacket.writeVarInt( item.ping, buf );
- buf.writeBoolean( item.displayName != null );
- if ( item.displayName != null )
- {
- DefinedPacket.writeString( item.displayName, buf );
- }
- break;
- case UPDATE_GAMEMODE:
- DefinedPacket.writeVarInt( item.gamemode, buf );
- break;
- case UPDATE_LATENCY:
- DefinedPacket.writeVarInt( item.ping, buf );
- break;
- case UPDATE_DISPLAY_NAME:
- buf.writeBoolean( item.displayName != null );
- if ( item.displayName != null )
- {
- DefinedPacket.writeString( item.displayName, buf );
- }
- break;
+ break;
+ }
}
}
}
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 6dcdece585..85decbb1df 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
@@ -4,6 +4,7 @@
import com.google.common.base.Predicate;
import net.md_5.bungee.protocol.DefinedPacket;
import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
import java.io.ByteArrayInputStream;
import java.io.DataInput;
import java.io.DataInputStream;
@@ -11,6 +12,7 @@
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
+import net.md_5.bungee.protocol.MinecraftInput;
import net.md_5.bungee.protocol.AbstractPacketHandler;
import net.md_5.bungee.protocol.ProtocolConstants;
@@ -42,17 +44,29 @@ public boolean apply(PluginMessage input)
public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{
tag = readString( buf );
- int maxSize = direction == ProtocolConstants.Direction.TO_SERVER ? Short.MAX_VALUE : 0x100000;
- Preconditions.checkArgument( buf.readableBytes() < maxSize );
- data = new byte[ buf.readableBytes() ];
- buf.readBytes( data );
+ if ( protocolVersion < ProtocolConstants.MINECRAFT_1_8 )
+ {
+ data = readArrayLegacy( buf );
+ } else
+ {
+ int maxSize = direction == ProtocolConstants.Direction.TO_SERVER ? Short.MAX_VALUE : 0x100000;
+ Preconditions.checkArgument(buf.readableBytes() < maxSize);
+ data = new byte[ buf.readableBytes() ];
+ buf.readBytes( data );
+ }
}
@Override
public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{
writeString( tag, buf );
- buf.writeBytes( data );
+ if ( protocolVersion < ProtocolConstants.MINECRAFT_1_8 )
+ {
+ writeArrayLegacy( data, buf, allowExtendedPacket );
+ } else
+ {
+ buf.writeBytes( data );
+ }
}
@Override
@@ -65,4 +79,9 @@ public DataInput getStream()
{
return new DataInputStream( new ByteArrayInputStream( data ) );
}
+
+ public MinecraftInput getMCStream()
+ {
+ return new MinecraftInput( Unpooled.wrappedBuffer( data ) );
+ }
}
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 ef9b8cf68a..a650b48245 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
@@ -28,8 +28,12 @@ public class ScoreboardObjective extends DefinedPacket
public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{
name = readString( buf );
+ if ( protocolVersion <= ProtocolConstants.MINECRAFT_1_7_6 )
+ {
+ value = readString( buf );
+ }
action = buf.readByte();
- if ( action == 0 || action == 2 )
+ if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_8 && ( action == 0 || action == 2 ) )
{
value = readString( buf );
type = readString( buf );
@@ -40,8 +44,12 @@ public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protoco
public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{
writeString( name, buf );
+ if ( protocolVersion <= ProtocolConstants.MINECRAFT_1_7_6 )
+ {
+ writeString( value, buf );
+ }
buf.writeByte( action );
- if ( action == 0 || action == 2 )
+ if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_8 && ( action == 0 || action == 2 ) )
{
writeString( value, buf );
writeString( type, buf );
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 6f0de535d4..e8157005c8 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
@@ -29,10 +29,20 @@ public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protoco
{
itemName = readString( buf );
action = buf.readByte();
- scoreName = readString( buf );
- if ( action != 1 )
+ if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_8 )
{
- value = readVarInt( buf );
+ scoreName = readString( buf );
+ if ( action != 1 )
+ {
+ value = readVarInt( buf );
+ }
+ } else
+ {
+ if ( action != 1 )
+ {
+ scoreName = readString( buf );
+ value = buf.readInt();
+ }
}
}
@@ -41,10 +51,20 @@ public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protoc
{
writeString( itemName, buf );
buf.writeByte( action );
- writeString( scoreName, buf );
- if ( action != 1 )
+ if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_8 )
+ {
+ writeString( scoreName, buf );
+ if ( action != 1 )
+ {
+ writeVarInt( value, buf );
+ }
+ } else
{
- writeVarInt( value, buf );
+ if ( action != 1 )
+ {
+ writeString( scoreName, buf );
+ buf.writeInt( value );
+ }
}
}
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 e3bcbc330b..5234252aa1 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
@@ -25,14 +25,17 @@ public class TabCompleteRequest extends DefinedPacket
public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{
cursor = readString( buf );
- if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_9 )
+ if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_8 )
{
- assumeCommand = buf.readBoolean();
- }
-
- if ( hasPositon = buf.readBoolean() )
- {
- position = buf.readLong();
+ if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_9 )
+ {
+ assumeCommand = buf.readBoolean();
+ }
+
+ if ( hasPositon = buf.readBoolean() )
+ {
+ position = buf.readLong();
+ }
}
}
@@ -40,15 +43,18 @@ public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protoco
public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion)
{
writeString( cursor, buf );
- if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_9 )
- {
- buf.writeBoolean( assumeCommand );
- }
-
- buf.writeBoolean( hasPositon );
- if ( hasPositon )
+ if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_8 )
{
- buf.writeLong( position );
+ if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_9 )
+ {
+ buf.writeBoolean( assumeCommand );
+ }
+
+ buf.writeBoolean( hasPositon );
+ if ( hasPositon )
+ {
+ buf.writeLong( position );
+ }
}
}
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 b470579952..a5247a8601 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
@@ -50,16 +50,19 @@ public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protoco
prefix = readString( buf );
suffix = readString( buf );
friendlyFire = buf.readByte();
- nameTagVisibility = readString( buf );
- if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_9 )
+ if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_8 )
{
- collisionRule = readString( buf );
+ nameTagVisibility = readString( buf );
+ if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_9 )
+ {
+ collisionRule = readString(buf);
+ }
+ color = buf.readByte();
}
- color = buf.readByte();
}
if ( mode == 0 || mode == 3 || mode == 4 )
{
- int len = readVarInt( buf );
+ int len = ( protocolVersion >= ProtocolConstants.MINECRAFT_1_8 ) ? readVarInt( buf ) : buf.readShort();
players = new String[ len ];
for ( int i = 0; i < len; i++ )
{
@@ -79,16 +82,25 @@ public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protoc
writeString( prefix, buf );
writeString( suffix, buf );
buf.writeByte( friendlyFire );
- writeString( nameTagVisibility, buf );
- if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_9 )
+ if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_8 )
{
- writeString( collisionRule, buf );
+ writeString( nameTagVisibility, buf );
+ if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_9 )
+ {
+ writeString( collisionRule, buf);
+ }
+ buf.writeByte( color );
}
- buf.writeByte( color );
}
if ( mode == 0 || mode == 3 || mode == 4 )
{
- writeVarInt( players.length, buf );
+ if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_8 )
+ {
+ writeVarInt( players.length, buf );
+ } else
+ {
+ buf.writeShort( players.length );
+ }
for ( String player : players )
{
writeString( player, buf );
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 b4c8bcfc06..f889533261 100644
--- a/proxy/src/main/java/net/md_5/bungee/BungeeCord.java
+++ b/proxy/src/main/java/net/md_5/bungee/BungeeCord.java
@@ -151,7 +151,13 @@ public class BungeeCord extends ProxyServer
.registerTypeAdapter( BaseComponent.class, new ComponentSerializer() )
.registerTypeAdapter( TextComponent.class, new TextComponentSerializer() )
.registerTypeAdapter( TranslatableComponent.class, new TranslatableComponentSerializer() )
- .registerTypeAdapter( ServerPing.PlayerInfo.class, new PlayerInfoSerializer() )
+ .registerTypeAdapter( ServerPing.PlayerInfo.class, new PlayerInfoSerializer( ProtocolConstants.MINECRAFT_1_7_6 ) )
+ .registerTypeAdapter( Favicon.class, Favicon.getFaviconTypeAdapter() ).create();
+ 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();
@Getter
private ConnectionThrottle connectionThrottle;
@@ -475,7 +481,7 @@ public void broadcast(DefinedPacket packet)
@Override
public String getName()
{
- return "BungeeCord";
+ return config.getCustomServerName();
}
@Override
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 494213db8e..e9073c5d4c 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.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,11 +152,14 @@ private static void sendPacket(ProxiedPlayer player, DefinedPacket packet)
@Override
public Title send(ProxiedPlayer player)
{
- sendPacket( player, clear );
- sendPacket( player, reset );
- sendPacket( player, times );
- sendPacket( player, subtitle );
- sendPacket( player, title );
+ if ( player.getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_8 )
+ {
+ sendPacket( player, clear );
+ sendPacket( player, reset );
+ sendPacket( player, times );
+ sendPacket( player, subtitle );
+ sendPacket( player, title );
+ }
return this;
}
}
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 491cf1a168..bba0641b08 100644
--- a/proxy/src/main/java/net/md_5/bungee/PlayerInfoSerializer.java
+++ b/proxy/src/main/java/net/md_5/bungee/PlayerInfoSerializer.java
@@ -13,14 +13,20 @@
public class PlayerInfoSerializer implements JsonSerializer, JsonDeserializer
{
+ private final int protocol;
+ public PlayerInfoSerializer(int protocol)
+ {
+ this.protocol = protocol;
+ }
+
@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 ( protocol == 4 || !id.contains( "-" ) )
{
info.setId( id );
} else
@@ -35,7 +41,13 @@ public JsonElement serialize(ServerPing.PlayerInfo src, Type typeOfSrc, JsonSeri
{
JsonObject out = new JsonObject();
out.addProperty( "name", src.getName() );
- out.addProperty( "id", src.getUniqueId().toString() );
+ if ( protocol == 4 )
+ {
+ out.addProperty( "id", src.getId() );
+ } else
+ {
+ out.addProperty( "id", src.getUniqueId().toString() );
+ }
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 6c31f15ff3..0d51263c8a 100644
--- a/proxy/src/main/java/net/md_5/bungee/ServerConnector.java
+++ b/proxy/src/main/java/net/md_5/bungee/ServerConnector.java
@@ -1,11 +1,14 @@
package net.md_5.bungee;
-import com.google.common.base.Preconditions;
-import io.netty.buffer.ByteBuf;
-import io.netty.buffer.ByteBufAllocator;
+import java.util.Arrays;
import java.util.Queue;
import java.util.Set;
import java.util.UUID;
+
+import com.google.common.base.Preconditions;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.ByteBufAllocator;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import net.md_5.bungee.api.ChatColor;
@@ -29,7 +32,9 @@
import net.md_5.bungee.netty.HandlerBoss;
import net.md_5.bungee.netty.PacketHandler;
import net.md_5.bungee.protocol.DefinedPacket;
+import net.md_5.bungee.protocol.MinecraftOutput;
import net.md_5.bungee.protocol.Protocol;
+import net.md_5.bungee.protocol.ProtocolConstants;
import net.md_5.bungee.protocol.packet.EncryptionRequest;
import net.md_5.bungee.protocol.packet.Handshake;
import net.md_5.bungee.protocol.packet.Kick;
@@ -42,88 +47,111 @@
import net.md_5.bungee.protocol.packet.ScoreboardScore;
import net.md_5.bungee.protocol.packet.SetCompression;
+
@RequiredArgsConstructor
public class ServerConnector extends PacketHandler
{
-
- private final ProxyServer bungee;
- private ChannelWrapper ch;
- private final UserConnection user;
+
+ private final ProxyServer bungee;
+ private ChannelWrapper ch;
+ private final UserConnection user;
private final BungeeServerInfo target;
- private State thisState = State.LOGIN_SUCCESS;
+ private State thisState = State.LOGIN_SUCCESS;
@Getter
- private ForgeServerHandler handshakeHandler;
- private boolean obsolete;
-
+ private ForgeServerHandler handshakeHandler;
+ private boolean obsolete;
+
private enum State
{
-
- LOGIN_SUCCESS, ENCRYPT_RESPONSE, LOGIN, FINISHED;
+
+ LOGIN_SUCCESS,
+ ENCRYPT_RESPONSE,
+ LOGIN,
+ FINISHED;
}
-
+
@Override
public void exception(Throwable t) throws Exception
{
- if ( obsolete )
- {
+ if (obsolete)
return;
- }
-
- String message = "Exception Connecting:" + Util.exception( t );
- if ( user.getServer() == null )
- {
- user.disconnect( message );
- } else
- {
- user.sendMessage( ChatColor.RED + message );
- }
+
+ String message = "Exception Connecting:" + Util.exception(t);
+ if (user.getServer() == null)
+ user.disconnect(message);
+ else
+ user.sendMessage(ChatColor.RED + message);
}
-
+
@Override
public void connected(ChannelWrapper channel) throws Exception
{
this.ch = channel;
-
- this.handshakeHandler = new ForgeServerHandler( user, ch, target );
+
+ this.handshakeHandler = new ForgeServerHandler(user, ch, target);
Handshake originalHandshake = user.getPendingConnection().getHandshake();
- Handshake copiedHandshake = new Handshake( originalHandshake.getProtocolVersion(), originalHandshake.getHost(), originalHandshake.getPort(), 2 );
-
- if ( BungeeCord.getInstance().config.isIpForward() )
+ Handshake copiedHandshake = new Handshake(originalHandshake.getProtocolVersion(), originalHandshake.getHost(), originalHandshake.getPort(), 2);
+
+ if (BungeeCord.getInstance().config.isIpForward())
{
String newHost = copiedHandshake.getHost() + "\00" + user.getAddress().getHostString() + "\00" + user.getUUID();
+ // Handle properties.
+ LoginResult.Property[] properties = new LoginResult.Property[0];
+
LoginResult profile = user.getPendingConnection().getLoginProfile();
- if ( profile != null && profile.getProperties() != null && profile.getProperties().length > 0 )
+ if (profile != null && profile.getProperties() != null && profile.getProperties().length > 0)
{
- newHost += "\00" + BungeeCord.getInstance().gson.toJson( profile.getProperties() );
+ properties = profile.getProperties();
}
- copiedHandshake.setHost( newHost );
- } else if ( !user.getExtraDataInHandshake().isEmpty() )
- {
- // Only restore the extra data if IP forwarding is off.
- // TODO: Add support for this data with IP forwarding.
- copiedHandshake.setHost( copiedHandshake.getHost() + user.getExtraDataInHandshake() );
- }
- channel.write( copiedHandshake );
+ if ( user.getForgeClientHandler().isFmlTokenInHandshake() )
+ {
+ // Get the current properties and copy them into a slightly bigger array.
+ LoginResult.Property[] newp = Arrays.copyOf( properties, properties.length + 2 );
+
+ // Add a new profile property that specifies that this user is a Forge user.
+ newp[newp.length - 2] = new LoginResult.Property( ForgeConstants.FML_LOGIN_PROFILE, "true", null );
- channel.setProtocol( Protocol.LOGIN );
- channel.write( new LoginRequest( user.getName() ) );
- }
+ // If we do not perform the replacement, then the IP Forwarding code in Spigot et. al. will try to split on this prematurely.
+ newp[newp.length - 1] = new LoginResult.Property( ForgeConstants.EXTRA_DATA, user.getExtraDataInHandshake().replaceAll( "\0", "\1"), "" );
+
+ // All done.
+ properties = newp;
+ }
+
+ // If we touched any properties, then append them
+ if (properties.length > 0)
+ {
+ newHost += "\00" + BungeeCord.getInstance().gson.toJson(properties);
+ }
+ copiedHandshake.setHost(newHost);
+ }
+ else if (!user.getExtraDataInHandshake().isEmpty()) {
+ // Restore the extra data
+ copiedHandshake.setHost(copiedHandshake.getHost() + user.getExtraDataInHandshake());
+ }
+
+ channel.write(copiedHandshake);
+
+ channel.setProtocol(Protocol.LOGIN);
+ channel.write(new LoginRequest(user.getName()));
+}
+
@Override
public void disconnected(ChannelWrapper channel) throws Exception
{
- user.getPendingConnects().remove( target );
+ user.getPendingConnects().remove(target);
}
-
+
@Override
public void handle(LoginSuccess loginSuccess) throws Exception
{
- Preconditions.checkState( thisState == State.LOGIN_SUCCESS, "Not expecting LOGIN_SUCCESS" );
- ch.setProtocol( Protocol.GAME );
+ Preconditions.checkState(thisState == State.LOGIN_SUCCESS, "Not expecting LOGIN_SUCCESS");
+ ch.setProtocol(Protocol.GAME);
thisState = State.LOGIN;
-
+
// Only reset the Forge client when:
// 1) The user is switching servers (so has a current server)
// 2) The handshake is complete
@@ -137,38 +165,33 @@ public void handle(LoginSuccess loginSuccess) throws Exception
// we need to switch to a modded connection. However, we always need to reset the
// connection when we have a modded server regardless of where we go - doing it
// here makes sense.
- if ( user.getServer() != null && user.getForgeClientHandler().isHandshakeComplete()
- && user.getServer().isForgeServer() )
- {
+ if (user.getServer() != null && user.getForgeClientHandler().isHandshakeComplete() && user.getServer().isForgeServer())
user.getForgeClientHandler().resetHandshake();
- }
-
+
throw CancelSendSignal.INSTANCE;
}
-
+
@Override
public void handle(SetCompression setCompression) throws Exception
{
- ch.setCompressionThreshold( setCompression.getThreshold() );
+ ch.setCompressionThreshold(setCompression.getThreshold());
}
-
+
@Override
public void handle(Login login) throws Exception
{
- Preconditions.checkState( thisState == State.LOGIN, "Not expecting LOGIN" );
-
- ServerConnection server = new ServerConnection( ch, target );
- ServerConnectedEvent event = new ServerConnectedEvent( user, server );
- bungee.getPluginManager().callEvent( event );
-
- ch.write( BungeeCord.getInstance().registerChannels() );
+ Preconditions.checkState(thisState == State.LOGIN, "Not expecting LOGIN");
+
+ ServerConnection server = new ServerConnection(ch, target);
+ ServerConnectedEvent event = new ServerConnectedEvent(user, server);
+ bungee.getPluginManager().callEvent(event);
+
+ ch.write(BungeeCord.getInstance().registerChannels());
Queue packetQueue = target.getPacketQueue();
- synchronized ( packetQueue )
+ synchronized (packetQueue)
{
- while ( !packetQueue.isEmpty() )
- {
- ch.write( packetQueue.poll() );
- }
+ while (!packetQueue.isEmpty())
+ ch.write(packetQueue.poll());
}
for ( PluginMessage message : user.getPendingConnection().getRelayMessages() )
@@ -185,30 +208,51 @@ public void handle(Login login) throws Exception
{
user.getForgeClientHandler().setHandshakeComplete();
}
-
- if ( user.getServer() == null )
+
+ if (user.getServer() == null)
{
// Once again, first connection
- user.setClientEntityId( login.getEntityId() );
- user.setServerEntityId( login.getEntityId() );
-
+ user.setClientEntityId(login.getEntityId());
+ user.setServerEntityId(login.getEntityId());
+
// Set tab list size, this sucks balls, TODO: what shall we do about packet mutability
- Login modLogin = new Login( login.getEntityId(), login.getGameMode(), (byte) login.getDimension(), login.getDifficulty(),
- (byte) user.getPendingConnection().getListener().getTabListSize(), login.getLevelType(), login.isReducedDebugInfo() );
+ // Forge allows dimension ID's > 127
+
+ Login modLogin;
+ if ( handshakeHandler != null && handshakeHandler.isServerForge() )
+ {
+ modLogin = new Login( login.getEntityId(), login.getGameMode(), login.getDimension(), login.getDifficulty(),
+ (byte) user.getPendingConnection().getListener().getTabListSize(), login.getLevelType(), login.isReducedDebugInfo() );
+ }
+ else
+ {
+ modLogin = new Login( login.getEntityId(), login.getGameMode(), (byte) login.getDimension(), login.getDifficulty(),
+ (byte) user.getPendingConnection().getListener().getTabListSize(), login.getLevelType(), login.isReducedDebugInfo() );
+ }
user.unsafe().sendPacket( modLogin );
- ByteBuf brand = ByteBufAllocator.DEFAULT.heapBuffer();
- DefinedPacket.writeString( bungee.getName() + " (" + bungee.getVersion() + ")", brand );
- user.unsafe().sendPacket( new PluginMessage( "MC|Brand", DefinedPacket.toArray( brand ), handshakeHandler.isServerForge() ) );
- brand.release();
-
+ if (user.getPendingConnection().getVersion() < ProtocolConstants.MINECRAFT_1_8)
+ {
+ MinecraftOutput out = new MinecraftOutput();
+ out.writeStringUTF8WithoutLengthHeaderBecauseDinnerboneStuffedUpTheMCBrandPacket(ProxyServer.getInstance().getName() + " (" + ProxyServer.getInstance().getVersion() + ")");
+ user.unsafe().sendPacket(new PluginMessage("MC|Brand", out.toArray(), handshakeHandler.isServerForge()));
+ }
+ else
+ {
+ ByteBuf brand = ByteBufAllocator.DEFAULT.heapBuffer();
+ DefinedPacket.writeString( bungee.getName() + " (" + bungee.getVersion() + ")", brand );
+ user.unsafe().sendPacket( new PluginMessage( "MC|Brand", DefinedPacket.toArray( brand ), handshakeHandler.isServerForge() ) );
+ brand.release();
+ }
+
user.setDimension( login.getDimension() );
- } else
+ }
+ else
{
- user.getServer().setObsolete( true );
+ user.getServer().setObsolete(true);
user.getTabListHandler().onServerChange();
-
+
Scoreboard serverScoreboard = user.getServerSentScoreboard();
for ( Objective objective : serverScoreboard.getObjectives() )
{
@@ -219,16 +263,12 @@ public void handle(Login login) throws Exception
user.unsafe().sendPacket( new ScoreboardScore( score.getItemName(), (byte) 1, score.getScoreName(), score.getValue() ) );
}
for ( Team team : serverScoreboard.getTeams() )
- {
- user.unsafe().sendPacket( new net.md_5.bungee.protocol.packet.Team( team.getName() ) );
- }
+ user.unsafe().sendPacket(new net.md_5.bungee.protocol.packet.Team(team.getName()));
serverScoreboard.clear();
-
- for ( UUID bossbar : user.getSentBossBars() )
- {
+
+ for (UUID bossbar : user.getSentBossBars())
// Send remove bossbar packet
- user.unsafe().sendPacket( new net.md_5.bungee.protocol.packet.BossBar( bossbar, 1 ) );
- }
+ user.unsafe().sendPacket(new net.md_5.bungee.protocol.packet.BossBar(bossbar, 1));
user.getSentBossBars().clear();
user.setDimensionChange( true );
@@ -242,117 +282,107 @@ public void handle(Login login) throws Exception
user.setDimension( login.getDimension() );
// Remove from old servers
- user.getServer().disconnect( "Quitting" );
+ user.getServer().disconnect("Quitting");
}
-
+
// TODO: Fix this?
- if ( !user.isActive() )
+ if (!user.isActive())
{
- server.disconnect( "Quitting" );
+ server.disconnect("Quitting");
// Silly server admins see stack trace and die
- bungee.getLogger().warning( "No client connected for pending server!" );
+ bungee.getLogger().warning("No client connected for pending server!");
return;
}
-
+
// Add to new server
// TODO: Move this to the connected() method of DownstreamBridge
- target.addPlayer( user );
- user.getPendingConnects().remove( target );
- user.setServerJoinQueue( null );
- user.setDimensionChange( false );
-
- user.setServer( server );
- ch.getHandle().pipeline().get( HandlerBoss.class ).setHandler( new DownstreamBridge( bungee, user, server ) );
-
- bungee.getPluginManager().callEvent( new ServerSwitchEvent( user ) );
-
+ target.addPlayer(user);
+ user.getPendingConnects().remove(target);
+ user.setServerJoinQueue(null);
+ user.setDimensionChange(false);
+
+ user.setServer(server);
+ ch.getHandle().pipeline().get(HandlerBoss.class).setHandler(new DownstreamBridge(bungee, user, server));
+
+ bungee.getPluginManager().callEvent(new ServerSwitchEvent(user));
+
thisState = State.FINISHED;
-
+
throw CancelSendSignal.INSTANCE;
}
-
+
@Override
public void handle(EncryptionRequest encryptionRequest) throws Exception
{
- throw new RuntimeException( "Server is online mode!" );
+ throw new RuntimeException("Server is online mode!");
}
-
+
@Override
public void handle(Kick kick) throws Exception
{
- ServerInfo def = user.updateAndGetNextServer( target );
- ServerKickEvent event = new ServerKickEvent( user, target, ComponentSerializer.parse( kick.getMessage() ), def, ServerKickEvent.State.CONNECTING );
- if ( event.getKickReason().toLowerCase().contains( "outdated" ) && def != null )
- {
+ ServerInfo def = user.updateAndGetNextServer(target);
+ 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 )
+ event.setCancelled(true);
+ bungee.getPluginManager().callEvent(event);
+ if (event.isCancelled() && event.getCancelServer() != null)
{
obsolete = true;
- user.connect( event.getCancelServer() );
+ user.connect(event.getCancelServer());
throw CancelSendSignal.INSTANCE;
}
-
- String message = bungee.getTranslation( "connect_kick", target.getName(), event.getKickReason() );
- if ( user.isDimensionChange() )
- {
- user.disconnect( message );
- } else
- {
- user.sendMessage( message );
- }
-
+
+ String message = bungee.getTranslation("connect_kick", target.getName(), event.getKickReason());
+ if (user.isDimensionChange())
+ user.disconnect(message);
+ else
+ user.sendMessage(message);
+
throw CancelSendSignal.INSTANCE;
}
-
+
@Override
public void handle(PluginMessage pluginMessage) throws Exception
{
- if ( pluginMessage.getTag().equals( ForgeConstants.FML_REGISTER ) )
+ if (pluginMessage.getTag().equals(ForgeConstants.FML_REGISTER))
{
- Set channels = ForgeUtils.readRegisteredChannels( pluginMessage );
+ Set channels = ForgeUtils.readRegisteredChannels(pluginMessage);
boolean isForgeServer = false;
- for ( String channel : channels )
- {
- if ( channel.equals( ForgeConstants.FML_HANDSHAKE_TAG ) )
+ for (String channel : channels)
+ if (channel.equals(ForgeConstants.FML_HANDSHAKE_TAG))
{
// If we have a completed handshake and we have been asked to register a FML|HS
// packet, let's send the reset packet now. Then, we can continue the message sending.
// The handshake will not be complete if we reset this earlier.
- if ( user.getServer() != null && user.getForgeClientHandler().isHandshakeComplete() )
- {
+ if (user.getServer() != null && user.getForgeClientHandler().isHandshakeComplete())
user.getForgeClientHandler().resetHandshake();
- }
-
+
isForgeServer = true;
break;
}
- }
-
- if ( isForgeServer && !this.handshakeHandler.isServerForge() )
+
+ if (isForgeServer && !this.handshakeHandler.isServerForge())
{
// We now set the server-side handshake handler for the client to this.
handshakeHandler.setServerAsForgeServer();
- user.setForgeServerHandler( handshakeHandler );
+ user.setForgeServerHandler(handshakeHandler);
}
}
-
- if ( pluginMessage.getTag().equals( ForgeConstants.FML_HANDSHAKE_TAG ) || pluginMessage.getTag().equals( ForgeConstants.FORGE_REGISTER ) )
+
+ if (!handshakeHandler.isHandshakeComplete() && ( pluginMessage.getTag().equals(ForgeConstants.FML_HANDSHAKE_TAG) || pluginMessage.getTag().equals(ForgeConstants.FORGE_REGISTER ) ))
{
- this.handshakeHandler.handle( pluginMessage );
-
+ handshakeHandler.handle( pluginMessage );
+
// We send the message as part of the handler, so don't send it here.
throw CancelSendSignal.INSTANCE;
- } else
- {
+ }
+ 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 );
- }
+ user.unsafe().sendPacket(pluginMessage);
}
-
+
@Override
public String toString()
{
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 93df974770..2ef0d74d8c 100644
--- a/proxy/src/main/java/net/md_5/bungee/UserConnection.java
+++ b/proxy/src/main/java/net/md_5/bungee/UserConnection.java
@@ -56,7 +56,6 @@
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.Respawn;
import net.md_5.bungee.protocol.packet.SetCompression;
import net.md_5.bungee.tab.ServerUnique;
import net.md_5.bungee.tab.TabList;
@@ -178,8 +177,12 @@ public void init()
forgeClientHandler = new ForgeClientHandler( this );
+ // No-config FML handshake marker.
// Set whether the connection has a 1.8 FML marker in the handshake.
- forgeClientHandler.setFmlTokenInHandshake( this.getPendingConnection().getExtraDataInHandshake().contains( ForgeConstants.FML_HANDSHAKE_TOKEN ) );
+ if (this.getPendingConnection().getExtraDataInHandshake().contains( ForgeConstants.FML_HANDSHAKE_TOKEN ))
+ {
+ forgeClientHandler.setFmlTokenInHandshake( true );
+ }
}
public void sendPacket(PacketWrapper packet)
@@ -197,6 +200,10 @@ public boolean isActive()
public void setDisplayName(String name)
{
Preconditions.checkNotNull( name, "displayName" );
+ if( pendingConnection.getVersion() <= ProtocolConstants.MINECRAFT_1_7_6 )
+ {
+ Preconditions.checkArgument( name.length() <= 16, "Display name cannot be longer than 16 characters" );
+ }
displayName = name;
}
@@ -419,7 +426,7 @@ private void sendMessage(ChatMessageType position, String message)
public void sendMessage(ChatMessageType position, BaseComponent... 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 && pendingConnection.getVersion() >= ProtocolConstants.MINECRAFT_1_8 )
{
sendMessage( position, ComponentSerializer.toString( new TextComponent( BaseComponent.toLegacyText( message ) ) ) );
} else
@@ -432,7 +439,7 @@ public void sendMessage(ChatMessageType position, BaseComponent... message)
public void sendMessage(ChatMessageType position, BaseComponent 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 && pendingConnection.getVersion() >= ProtocolConstants.MINECRAFT_1_8 )
{
sendMessage( position, ComponentSerializer.toString( new TextComponent( BaseComponent.toLegacyText( message ) ) ) );
} else
@@ -613,19 +620,25 @@ public Map getModList()
@Override
public void setTabHeader(BaseComponent header, BaseComponent footer)
{
- unsafe().sendPacket( new PlayerListHeaderFooter(
- ( header != null ) ? ComponentSerializer.toString( header ) : EMPTY_TEXT,
- ( footer != null ) ? ComponentSerializer.toString( footer ) : EMPTY_TEXT
- ) );
+ if ( pendingConnection.getVersion() >= ProtocolConstants.MINECRAFT_1_8 )
+ {
+ unsafe().sendPacket( new PlayerListHeaderFooter(
+ ( header != null ) ? ComponentSerializer.toString( header ) : EMPTY_TEXT,
+ ( footer != null ) ? ComponentSerializer.toString( footer ) : EMPTY_TEXT
+ ) );
+ }
}
@Override
public void setTabHeader(BaseComponent[] header, BaseComponent[] footer)
{
- unsafe().sendPacket( new PlayerListHeaderFooter(
- ( header != null ) ? ComponentSerializer.toString( header ) : EMPTY_TEXT,
- ( footer != null ) ? ComponentSerializer.toString( footer ) : EMPTY_TEXT
- ) );
+ if ( pendingConnection.getVersion() >= ProtocolConstants.MINECRAFT_1_8 )
+ {
+ unsafe().sendPacket( new PlayerListHeaderFooter(
+ ( header != null ) ? ComponentSerializer.toString( header ) : EMPTY_TEXT,
+ ( footer != null ) ? ComponentSerializer.toString( footer ) : EMPTY_TEXT
+ ) );
+ }
}
@Override
@@ -648,7 +661,7 @@ public String getExtraDataInHandshake()
public void setCompressionThreshold(int compressionThreshold)
{
- if ( !ch.isClosing() && this.compressionThreshold == -1 && compressionThreshold >= 0 )
+ if ( !ch.isClosing() && this.compressionThreshold == -1 && getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_8 && compressionThreshold >= 0 )
{
this.compressionThreshold = compressionThreshold;
unsafe.sendPacket( new SetCompression( compressionThreshold ) );
diff --git a/proxy/src/main/java/net/md_5/bungee/command/CommandBungee.java b/proxy/src/main/java/net/md_5/bungee/command/CommandBungee.java
index b07987915f..5bb1dee6cd 100644
--- a/proxy/src/main/java/net/md_5/bungee/command/CommandBungee.java
+++ b/proxy/src/main/java/net/md_5/bungee/command/CommandBungee.java
@@ -16,6 +16,7 @@ public CommandBungee()
@Override
public void execute(CommandSender sender, String[] args)
{
- sender.sendMessage( ChatColor.BLUE + "This server is running BungeeCord version " + ProxyServer.getInstance().getVersion() + " by md_5" );
+ sender.sendMessage( ChatColor.BLUE + "This server is running " + ProxyServer.getInstance().getName() + " version " + ProxyServer.getInstance().getVersion() + " by md_5" );
+ sender.sendMessage( ChatColor.BLUE + "Protocol support for 1.7.x by Zartec, ghac and I9hdkill" );
}
}
diff --git a/proxy/src/main/java/net/md_5/bungee/conf/Configuration.java b/proxy/src/main/java/net/md_5/bungee/conf/Configuration.java
index 907246a98a..8b776dbad1 100644
--- a/proxy/src/main/java/net/md_5/bungee/conf/Configuration.java
+++ b/proxy/src/main/java/net/md_5/bungee/conf/Configuration.java
@@ -57,6 +57,8 @@ public class Configuration implements ProxyConfig
private boolean ipForward;
private Favicon favicon;
private int compressionThreshold = 256;
+ private String customServerName = "HexaCord";
+ private boolean alwaysHandlePackets = false;
private boolean preventProxyConnections;
public void load()
@@ -85,6 +87,8 @@ public void load()
throttle = adapter.getInt( "connection_throttle", throttle );
ipForward = adapter.getBoolean( "ip_forward", ipForward );
compressionThreshold = adapter.getInt( "network_compression_threshold", compressionThreshold );
+ customServerName = adapter.getString( "custom_server_name", "HexaCord" );
+ alwaysHandlePackets = adapter.getBoolean( "always_handle_packets", false );
preventProxyConnections = adapter.getBoolean( "prevent_proxy_connections", preventProxyConnections );
disabledCommands = new CaseInsensitiveSet( (Collection) adapter.getList( "disabled_commands", Arrays.asList( "disabledcommandhere" ) ) );
@@ -144,4 +148,15 @@ public Favicon getFaviconObject()
{
return favicon;
}
+
+ @Override
+ public String getCustomServerName()
+ {
+ return customServerName;
+ }
+
+ @Override
+ public boolean getAlwaysHandlePackets() {
+ return alwaysHandlePackets;
+ }
}
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 6b8ae2452c..253126a829 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
@@ -1,24 +1,27 @@
package net.md_5.bungee.connection;
+
+import java.io.DataInput;
+
import com.google.common.base.Preconditions;
import com.google.common.io.ByteArrayDataOutput;
import com.google.common.io.ByteStreams;
-import java.io.DataInput;
+
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.buffer.Unpooled;
import lombok.RequiredArgsConstructor;
import net.md_5.bungee.ServerConnection;
-import net.md_5.bungee.api.chat.TextComponent;
-import net.md_5.bungee.api.event.ServerDisconnectEvent;
-import net.md_5.bungee.api.event.TabCompleteResponseEvent;
import net.md_5.bungee.UserConnection;
import net.md_5.bungee.Util;
import net.md_5.bungee.api.ProxyServer;
+import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.event.PluginMessageEvent;
+import net.md_5.bungee.api.event.ServerDisconnectEvent;
import net.md_5.bungee.api.event.ServerKickEvent;
+import net.md_5.bungee.api.event.TabCompleteResponseEvent;
import net.md_5.bungee.api.score.Objective;
import net.md_5.bungee.api.score.Position;
import net.md_5.bungee.api.score.Score;
@@ -29,105 +32,100 @@
import net.md_5.bungee.netty.PacketHandler;
import net.md_5.bungee.protocol.DefinedPacket;
import net.md_5.bungee.protocol.PacketWrapper;
+import net.md_5.bungee.protocol.ProtocolConstants;
import net.md_5.bungee.protocol.packet.BossBar;
import net.md_5.bungee.protocol.packet.KeepAlive;
+import net.md_5.bungee.protocol.packet.Kick;
import net.md_5.bungee.protocol.packet.PlayerListItem;
+import net.md_5.bungee.protocol.packet.PluginMessage;
import net.md_5.bungee.protocol.packet.Respawn;
+import net.md_5.bungee.protocol.packet.ScoreboardDisplay;
import net.md_5.bungee.protocol.packet.ScoreboardObjective;
import net.md_5.bungee.protocol.packet.ScoreboardScore;
-import net.md_5.bungee.protocol.packet.ScoreboardDisplay;
-import net.md_5.bungee.protocol.packet.PluginMessage;
-import net.md_5.bungee.protocol.packet.Kick;
import net.md_5.bungee.protocol.packet.SetCompression;
import net.md_5.bungee.protocol.packet.TabCompleteResponse;
import net.md_5.bungee.tab.TabList;
+
@RequiredArgsConstructor
public class DownstreamBridge extends PacketHandler
{
-
- private final ProxyServer bungee;
- private final UserConnection con;
+
+ private final ProxyServer bungee;
+ private final UserConnection con;
private final ServerConnection server;
-
+
@Override
public void exception(Throwable t) throws Exception
{
- if ( server.isObsolete() )
- {
+ if (server.isObsolete())
// do not perform any actions if the user has already moved
return;
- }
ServerInfo def = con.updateAndGetNextServer( server.getInfo() );
if ( def != null )
{
- server.setObsolete( true );
- con.connectNow( def );
- con.sendMessage( bungee.getTranslation( "server_went_down" ) );
- } else
- {
- con.disconnect( Util.exception( t ) );
+ server.setObsolete(true);
+ con.connectNow(def);
+ con.sendMessage(bungee.getTranslation("server_went_down"));
}
+ else
+ con.disconnect(Util.exception(t));
}
-
+
@Override
public void disconnected(ChannelWrapper channel) throws Exception
{
// We lost connection to the server
- server.getInfo().removePlayer( con );
- if ( bungee.getReconnectHandler() != null )
- {
- bungee.getReconnectHandler().setServer( con );
- }
-
- if ( !server.isObsolete() )
- {
- con.disconnect( bungee.getTranslation( "lost_connection" ) );
- }
-
- ServerDisconnectEvent serverDisconnectEvent = new ServerDisconnectEvent( con, server.getInfo() );
- bungee.getPluginManager().callEvent( serverDisconnectEvent );
+ server.getInfo().removePlayer(con);
+ if (bungee.getReconnectHandler() != null)
+ bungee.getReconnectHandler().setServer(con);
+
+ if (!server.isObsolete())
+ con.disconnect(bungee.getTranslation("lost_connection"));
+
+ ServerDisconnectEvent serverDisconnectEvent = new ServerDisconnectEvent(con, server.getInfo());
+ bungee.getPluginManager().callEvent(serverDisconnectEvent);
}
-
+
@Override
public boolean shouldHandle(PacketWrapper packet) throws Exception
{
return !server.isObsolete();
}
-
+
@Override
public void handle(PacketWrapper packet) throws Exception
{
- con.getEntityRewrite().rewriteClientbound( packet.buf, con.getServerEntityId(), con.getClientEntityId() );
- con.sendPacket( packet );
+ con.getEntityRewrite().rewriteClientbound(packet.buf, con.getServerEntityId(), con.getClientEntityId());
+ con.sendPacket(packet);
}
-
+
@Override
public void handle(KeepAlive alive) throws Exception
{
server.setSentPingId( alive.getRandomId() );
con.setSentPingTime( System.currentTimeMillis() );
}
-
+
@Override
public void handle(PlayerListItem playerList) throws Exception
{
- con.getTabListHandler().onUpdate( TabList.rewrite( playerList ) );
+ con.getTabListHandler().onUpdate(TabList.rewrite(playerList));
throw CancelSendSignal.INSTANCE; // Always throw because of profile rewriting
}
-
+
@Override
public void handle(ScoreboardObjective objective) throws Exception
{
Scoreboard serverScoreboard = con.getServerSentScoreboard();
- switch ( objective.getAction() )
+ switch (objective.getAction())
{
case 0:
- serverScoreboard.addObjective( new Objective( objective.getName(), objective.getValue(), objective.getType() ) );
+ serverScoreboard.addObjective(new Objective(objective.getName(), objective.getValue(), objective.getType()));
break;
case 1:
- serverScoreboard.removeObjective( objective.getName() );
+ serverScoreboard.removeObjective(objective.getName());
break;
case 2:
Objective oldObjective = serverScoreboard.getObjective( objective.getName() );
@@ -138,59 +136,58 @@ public void handle(ScoreboardObjective objective) throws Exception
}
break;
default:
- throw new IllegalArgumentException( "Unknown objective action: " + objective.getAction() );
+ throw new IllegalArgumentException("Unknown objective action: " + objective.getAction());
}
}
-
+
@Override
public void handle(ScoreboardScore score) throws Exception
{
Scoreboard serverScoreboard = con.getServerSentScoreboard();
- switch ( score.getAction() )
+ switch (score.getAction())
{
case 0:
- Score s = new Score( score.getItemName(), score.getScoreName(), score.getValue() );
- serverScoreboard.removeScore( score.getItemName() );
- serverScoreboard.addScore( s );
+ Score s = new Score(score.getItemName(), score.getScoreName(), score.getValue());
+ serverScoreboard.removeScore(score.getItemName());
+ serverScoreboard.addScore(s);
break;
case 1:
- serverScoreboard.removeScore( score.getItemName() );
+ serverScoreboard.removeScore(score.getItemName());
break;
default:
- throw new IllegalArgumentException( "Unknown scoreboard action: " + score.getAction() );
+ throw new IllegalArgumentException("Unknown scoreboard action: " + score.getAction());
}
}
-
+
@Override
public void handle(ScoreboardDisplay displayScoreboard) throws Exception
{
Scoreboard serverScoreboard = con.getServerSentScoreboard();
- serverScoreboard.setName( displayScoreboard.getName() );
- serverScoreboard.setPosition( Position.values()[displayScoreboard.getPosition()] );
+ serverScoreboard.setName(displayScoreboard.getName());
+ serverScoreboard.setPosition(Position.values()[displayScoreboard.getPosition()]);
}
-
+
@Override
public void handle(net.md_5.bungee.protocol.packet.Team team) throws Exception
{
Scoreboard serverScoreboard = con.getServerSentScoreboard();
// Remove team and move on
- if ( team.getMode() == 1 )
+ if (team.getMode() == 1)
{
- serverScoreboard.removeTeam( team.getName() );
+ serverScoreboard.removeTeam(team.getName());
return;
}
-
+
// Create or get old team
Team t;
- if ( team.getMode() == 0 )
+ if (team.getMode() == 0)
{
- t = new Team( team.getName() );
- serverScoreboard.addTeam( t );
- } else
- {
- t = serverScoreboard.getTeam( team.getName() );
+ t = new Team(team.getName());
+ serverScoreboard.addTeam(t);
}
-
+ else
+ t = serverScoreboard.getTeam(team.getName());
+
if ( t != null )
{
if ( team.getMode() == 0 || team.getMode() == 2 )
@@ -218,238 +215,233 @@ public void handle(net.md_5.bungee.protocol.packet.Team team) throws Exception
}
}
}
-
+
@Override
public void handle(PluginMessage pluginMessage) throws Exception
{
DataInput in = pluginMessage.getStream();
- PluginMessageEvent event = new PluginMessageEvent( con.getServer(), con, pluginMessage.getTag(), pluginMessage.getData().clone() );
-
- if ( bungee.getPluginManager().callEvent( event ).isCancelled() )
- {
+ PluginMessageEvent event = new PluginMessageEvent(con.getServer(), con, pluginMessage.getTag(), pluginMessage.getData().clone());
+
+ if (bungee.getPluginManager().callEvent(event).isCancelled())
throw CancelSendSignal.INSTANCE;
- }
-
- if ( pluginMessage.getTag().equals( "MC|Brand" ) )
+
+ if (pluginMessage.getTag().equals("MC|Brand"))
{
- ByteBuf brand = Unpooled.wrappedBuffer( pluginMessage.getData() );
- String serverBrand = DefinedPacket.readString( brand );
- brand.release();
+ if (con.getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_8)
+ {
+ 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(DefinedPacket.readArray( brand ));
+ brand.release();
+ }
+ else
+ {
+ String serverBrand = new String(pluginMessage.getData(), "UTF-8");
- Preconditions.checkState( !serverBrand.contains( bungee.getName() ), "Cannot connect proxy to itself!" );
+ 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( DefinedPacket.toArray( brand ) );
- brand.release();
+ pluginMessage.setData((bungee.getName() + " (" + bungee.getVersion() + ")" + " <- " + serverBrand).getBytes("UTF-8"));
+ }
// changes in the packet are ignored so we need to send it manually
- con.unsafe().sendPacket( pluginMessage );
+ con.unsafe().sendPacket(pluginMessage);
throw CancelSendSignal.INSTANCE;
}
-
- if ( pluginMessage.getTag().equals( "BungeeCord" ) )
+
+ if (pluginMessage.getTag().equals("BungeeCord"))
{
ByteArrayDataOutput out = ByteStreams.newDataOutput();
String subChannel = in.readUTF();
-
- if ( subChannel.equals( "ForwardToPlayer" ) )
+
+ if (subChannel.equals("ForwardToPlayer"))
{
- ProxiedPlayer target = bungee.getPlayer( in.readUTF() );
- if ( target != null )
+ ProxiedPlayer target = bungee.getPlayer(in.readUTF());
+ if (target != null)
{
// Read data from server
String channel = in.readUTF();
short len = in.readShort();
- byte[] data = new byte[ len ];
- in.readFully( data );
-
+ byte[] data = new byte[len];
+ in.readFully(data);
+
// Prepare new data to send
- out.writeUTF( channel );
- out.writeShort( data.length );
- out.write( data );
+ out.writeUTF(channel);
+ out.writeShort(data.length);
+ out.write(data);
byte[] payload = out.toByteArray();
-
- target.getServer().sendData( "BungeeCord", payload );
+
+ target.getServer().sendData("BungeeCord", payload);
}
-
+
// Null out stream, important as we don't want to send to ourselves
out = null;
}
- if ( subChannel.equals( "Forward" ) )
+ if (subChannel.equals("Forward"))
{
// Read data from server
String target = in.readUTF();
String channel = in.readUTF();
short len = in.readShort();
- byte[] data = new byte[ len ];
- in.readFully( data );
-
+ byte[] data = new byte[len];
+ in.readFully(data);
+
// Prepare new data to send
- out.writeUTF( channel );
- out.writeShort( data.length );
- out.write( data );
+ out.writeUTF(channel);
+ out.writeShort(data.length);
+ out.write(data);
byte[] payload = out.toByteArray();
-
+
// Null out stream, important as we don't want to send to ourselves
out = null;
-
- if ( target.equals( "ALL" ) )
+
+ if (target.equals("ALL"))
{
- for ( ServerInfo server : bungee.getServers().values() )
- {
- if ( server != con.getServer().getInfo() )
- {
- server.sendData( "BungeeCord", payload );
- }
- }
- } else if ( target.equals( "ONLINE" ) )
+ for (ServerInfo server : bungee.getServers().values())
+ if (server != con.getServer().getInfo())
+ server.sendData("BungeeCord", payload);
+ }
+ else if (target.equals("ONLINE"))
{
- for ( ServerInfo server : bungee.getServers().values() )
- {
- if ( server != con.getServer().getInfo() )
- {
- server.sendData( "BungeeCord", payload, false );
- }
- }
- } else
+ for (ServerInfo server : bungee.getServers().values())
+ if (server != con.getServer().getInfo())
+ server.sendData("BungeeCord", payload, false);
+ }
+ else
{
- ServerInfo server = bungee.getServerInfo( target );
- if ( server != null )
- {
- server.sendData( "BungeeCord", payload );
- }
+ ServerInfo server = bungee.getServerInfo(target);
+ if (server != null)
+ server.sendData("BungeeCord", payload);
}
}
- if ( subChannel.equals( "Connect" ) )
+ if (subChannel.equals("Connect"))
{
- ServerInfo server = bungee.getServerInfo( in.readUTF() );
- if ( server != null )
- {
- con.connect( server );
- }
+ ServerInfo server = bungee.getServerInfo(in.readUTF());
+ if (server != null)
+ con.connect(server);
}
- if ( subChannel.equals( "ConnectOther" ) )
+ if (subChannel.equals("ConnectOther"))
{
- ProxiedPlayer player = bungee.getPlayer( in.readUTF() );
- if ( player != null )
+ ProxiedPlayer player = bungee.getPlayer(in.readUTF());
+ if (player != null)
{
- ServerInfo server = bungee.getServerInfo( in.readUTF() );
- if ( server != null )
- {
- player.connect( server );
- }
+ ServerInfo server = bungee.getServerInfo(in.readUTF());
+ if (server != null)
+ player.connect(server);
}
}
- if ( subChannel.equals( "IP" ) )
+ if (subChannel.equals("IP"))
{
- out.writeUTF( "IP" );
- out.writeUTF( con.getAddress().getHostString() );
- out.writeInt( con.getAddress().getPort() );
+ out.writeUTF("IP");
+ out.writeUTF(con.getAddress().getHostString());
+ out.writeInt(con.getAddress().getPort());
}
- if ( subChannel.equals( "PlayerCount" ) )
+ if (subChannel.equals("PlayerCount"))
{
String target = in.readUTF();
- out.writeUTF( "PlayerCount" );
- if ( target.equals( "ALL" ) )
+ out.writeUTF("PlayerCount");
+ if (target.equals("ALL"))
{
- out.writeUTF( "ALL" );
- out.writeInt( bungee.getOnlineCount() );
- } else
+ out.writeUTF("ALL");
+ out.writeInt(bungee.getOnlineCount());
+ }
+ else
{
- ServerInfo server = bungee.getServerInfo( target );
- if ( server != null )
+ ServerInfo server = bungee.getServerInfo(target);
+ if (server != null)
{
- out.writeUTF( server.getName() );
- out.writeInt( server.getPlayers().size() );
+ out.writeUTF(server.getName());
+ out.writeInt(server.getPlayers().size());
}
}
}
- if ( subChannel.equals( "PlayerList" ) )
+ if (subChannel.equals("PlayerList"))
{
String target = in.readUTF();
- out.writeUTF( "PlayerList" );
- if ( target.equals( "ALL" ) )
+ out.writeUTF("PlayerList");
+ if (target.equals("ALL"))
{
- out.writeUTF( "ALL" );
- out.writeUTF( Util.csv( bungee.getPlayers() ) );
- } else
+ out.writeUTF("ALL");
+ out.writeUTF(Util.csv(bungee.getPlayers()));
+ }
+ else
{
- ServerInfo server = bungee.getServerInfo( target );
- if ( server != null )
+ ServerInfo server = bungee.getServerInfo(target);
+ if (server != null)
{
- out.writeUTF( server.getName() );
- out.writeUTF( Util.csv( server.getPlayers() ) );
+ out.writeUTF(server.getName());
+ out.writeUTF(Util.csv(server.getPlayers()));
}
}
}
- if ( subChannel.equals( "GetServers" ) )
+ if (subChannel.equals("GetServers"))
{
- out.writeUTF( "GetServers" );
- out.writeUTF( Util.csv( bungee.getServers().keySet() ) );
+ out.writeUTF("GetServers");
+ out.writeUTF(Util.csv(bungee.getServers().keySet()));
}
- if ( subChannel.equals( "Message" ) )
+ if (subChannel.equals("Message"))
{
- ProxiedPlayer target = bungee.getPlayer( in.readUTF() );
- if ( target != null )
- {
- target.sendMessage( in.readUTF() );
- }
+ ProxiedPlayer target = bungee.getPlayer(in.readUTF());
+ if (target != null)
+ target.sendMessage(in.readUTF());
}
- if ( subChannel.equals( "GetServer" ) )
+ if (subChannel.equals("GetServer"))
{
- out.writeUTF( "GetServer" );
- out.writeUTF( server.getInfo().getName() );
+ out.writeUTF("GetServer");
+ out.writeUTF(server.getInfo().getName());
}
- if ( subChannel.equals( "UUID" ) )
+ if (subChannel.equals("UUID"))
{
- out.writeUTF( "UUID" );
- out.writeUTF( con.getUUID() );
+ out.writeUTF("UUID");
+ out.writeUTF(con.getUUID());
}
- if ( subChannel.equals( "UUIDOther" ) )
+ if (subChannel.equals("UUIDOther"))
{
- ProxiedPlayer player = bungee.getPlayer( in.readUTF() );
- if ( player != null )
+ ProxiedPlayer player = bungee.getPlayer(in.readUTF());
+ if (player != null)
{
- out.writeUTF( "UUIDOther" );
- out.writeUTF( player.getName() );
- out.writeUTF( player.getUUID() );
+ out.writeUTF("UUIDOther");
+ out.writeUTF(player.getName());
+ out.writeUTF(player.getUUID());
}
}
- if ( subChannel.equals( "ServerIP" ) )
+ if (subChannel.equals("ServerIP"))
{
- ServerInfo info = bungee.getServerInfo( in.readUTF() );
- if ( info != null )
+ ServerInfo info = bungee.getServerInfo(in.readUTF());
+ if (info != null)
{
- out.writeUTF( "ServerIP" );
- out.writeUTF( info.getName() );
- out.writeUTF( info.getAddress().getAddress().getHostAddress() );
- out.writeShort( info.getAddress().getPort() );
+ out.writeUTF("ServerIP");
+ out.writeUTF(info.getName());
+ out.writeUTF(info.getAddress().getAddress().getHostAddress());
+ out.writeShort(info.getAddress().getPort());
}
}
- if ( subChannel.equals( "KickPlayer" ) )
+ if (subChannel.equals("KickPlayer"))
{
- ProxiedPlayer player = bungee.getPlayer( in.readUTF() );
- if ( player != null )
+ ProxiedPlayer player = bungee.getPlayer(in.readUTF());
+ if (player != null)
{
String kickReason = in.readUTF();
- player.disconnect( new TextComponent( kickReason ) );
+ player.disconnect(new TextComponent(kickReason));
}
}
-
+
// Check we haven't set out to null, and we have written data, if so reply back back along the BungeeCord channel
- if ( out != null )
+ if (out != null)
{
byte[] b = out.toByteArray();
- if ( b.length != 0 )
- {
- con.getServer().sendData( "BungeeCord", b );
- }
+ if (b.length != 0)
+ con.getServer().sendData("BungeeCord", b);
}
-
+
throw CancelSendSignal.INSTANCE;
}
}
-
+
@Override
public void handle(Kick kick) throws Exception
{
@@ -465,42 +457,40 @@ public void handle(Kick kick) throws Exception
server.setObsolete( true );
throw CancelSendSignal.INSTANCE;
}
-
+
@Override
public void handle(SetCompression setCompression) throws Exception
{
- server.getCh().setCompressionThreshold( setCompression.getThreshold() );
+ server.getCh().setCompressionThreshold(setCompression.getThreshold());
}
-
+
@Override
public void handle(TabCompleteResponse tabCompleteResponse) throws Exception
{
- TabCompleteResponseEvent tabCompleteResponseEvent = new TabCompleteResponseEvent( con.getServer(), con, tabCompleteResponse.getCommands() );
-
- if ( !bungee.getPluginManager().callEvent( tabCompleteResponseEvent ).isCancelled() )
- {
- con.unsafe().sendPacket( tabCompleteResponse );
- }
-
+ TabCompleteResponseEvent tabCompleteResponseEvent = new TabCompleteResponseEvent(con.getServer(), con, tabCompleteResponse.getCommands());
+
+ if (!bungee.getPluginManager().callEvent(tabCompleteResponseEvent).isCancelled())
+ con.unsafe().sendPacket(tabCompleteResponse);
+
throw CancelSendSignal.INSTANCE;
}
-
+
@Override
public void handle(BossBar bossBar)
{
- switch ( bossBar.getAction() )
+ switch (bossBar.getAction())
{
// Handle add bossbar
case 0:
- con.getSentBossBars().add( bossBar.getUuid() );
+ con.getSentBossBars().add(bossBar.getUuid());
break;
// Handle remove bossbar
case 1:
- con.getSentBossBars().remove( bossBar.getUuid() );
+ con.getSentBossBars().remove(bossBar.getUuid());
break;
}
}
-
+
@Override
public void handle(Respawn respawn)
{
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 e596f82237..7b5157b4e3 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
@@ -222,7 +222,7 @@ public void done(ServerPing result, Throwable error)
@Override
public void done(ProxyPingEvent pingResult, Throwable error)
{
- Gson gson = BungeeCord.getInstance().gson;
+ Gson gson = handshake.getProtocolVersion() == ProtocolConstants.MINECRAFT_1_7_2 ? BungeeCord.getInstance().gsonLegacy : BungeeCord.getInstance().gson;
unsafe.sendPacket( new StatusResponse( gson.toJson( pingResult.getResponse() ) ) );
}
};
@@ -500,7 +500,13 @@ public void run()
userCon.setCompressionThreshold( BungeeCord.getInstance().config.getCompressionThreshold() );
userCon.init();
- unsafe.sendPacket( new LoginSuccess( getUniqueId().toString(), getName() ) ); // With dashes in between
+ if ( 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.
+ }
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 3cd5cf6962..ba3260f399 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
@@ -14,6 +14,7 @@
import net.md_5.bungee.protocol.MinecraftDecoder;
import net.md_5.bungee.protocol.MinecraftEncoder;
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;
@@ -52,7 +53,7 @@ public void exception(Throwable t) throws Exception
@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;
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 bb43810bbc..52e2ca17e1 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
@@ -75,7 +75,10 @@ public void disconnected(ChannelWrapper channel) throws Exception
} );
for ( ProxiedPlayer player : con.getServer().getInfo().getPlayers() )
{
- player.unsafe().sendPacket( packet );
+ if ( player.getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_8 )
+ {
+ player.unsafe().sendPacket( packet );
+ }
}
con.getServer().disconnect( "Quitting" );
}
@@ -100,7 +103,7 @@ public void writabilityChanged(ChannelWrapper channel) throws Exception
@Override
public boolean shouldHandle(PacketWrapper packet) throws Exception
{
- return con.getServer() != null || packet.packet instanceof PluginMessage;
+ return bungee.getConfig().getAlwaysHandlePackets() || con.getServer() != null || packet.packet instanceof PluginMessage;
}
@Override
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 847a3ecac7..dc08926ff8 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 static EntityMap getEntityMap(int version)
{
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:
@@ -211,12 +215,14 @@ private static void rewrite(ByteBuf packet, int oldId, int newId, boolean[] ints
int packetId = DefinedPacket.readVarInt( packet );
int packetIdLength = packet.readerIndex() - readerIndex;
- if ( ints[packetId] )
- {
- rewriteInt( packet, oldId, newId, readerIndex + packetIdLength );
- } else if ( varints[packetId] )
- {
- rewriteVarInt( packet, oldId, newId, readerIndex + packetIdLength );
+ if(packetId>=0) {
+ 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 0000000000..05097bba44
--- /dev/null
+++ b/proxy/src/main/java/net/md_5/bungee/entitymap/EntityMap_1_7_2.java
@@ -0,0 +1,100 @@
+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 );
+ }
+}
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 0000000000..301da0e700
--- /dev/null
+++ b/proxy/src/main/java/net/md_5/bungee/entitymap/EntityMap_1_7_6.java
@@ -0,0 +1,60 @@
+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 );
+ }
+}
diff --git a/proxy/src/main/java/net/md_5/bungee/forge/ForgeConstants.java b/proxy/src/main/java/net/md_5/bungee/forge/ForgeConstants.java
index 6dca204830..f5253b897b 100644
--- a/proxy/src/main/java/net/md_5/bungee/forge/ForgeConstants.java
+++ b/proxy/src/main/java/net/md_5/bungee/forge/ForgeConstants.java
@@ -14,6 +14,10 @@ public class ForgeConstants
public static final String FML_HANDSHAKE_TAG = "FML|HS";
public static final String FML_REGISTER = "REGISTER";
+ // Game profile key
+ public static final String FML_LOGIN_PROFILE = "forgeClient";
+ public static final String EXTRA_DATA = "extraData";
+
/**
* The FML 1.8 handshake token.
*/
diff --git a/proxy/src/main/java/net/md_5/bungee/forge/ForgeServerHandler.java b/proxy/src/main/java/net/md_5/bungee/forge/ForgeServerHandler.java
index 3fe5ec5fd3..56215d4b1c 100644
--- a/proxy/src/main/java/net/md_5/bungee/forge/ForgeServerHandler.java
+++ b/proxy/src/main/java/net/md_5/bungee/forge/ForgeServerHandler.java
@@ -82,4 +82,15 @@ public void setServerAsForgeServer()
{
serverForge = true;
}
+
+
+ /**
+ * Returns whether the handshake is complete.
+ *
+ * @return true
if the handshake has been completed.
+ */
+ public boolean isHandshakeComplete()
+ {
+ return this.state == ForgeServerHandshakeState.DONE;
+ }
}
diff --git a/proxy/src/main/java/net/md_5/bungee/forge/ForgeServerHandshakeState.java b/proxy/src/main/java/net/md_5/bungee/forge/ForgeServerHandshakeState.java
index d58b4945fd..00f92ad7d5 100644
--- a/proxy/src/main/java/net/md_5/bungee/forge/ForgeServerHandshakeState.java
+++ b/proxy/src/main/java/net/md_5/bungee/forge/ForgeServerHandshakeState.java
@@ -132,6 +132,9 @@ public ForgeServerHandshakeState handle(PluginMessage message, ChannelWrapper ch
@Override
public ForgeServerHandshakeState send(PluginMessage message, UserConnection con)
{
+ // Packets should never make it here but if they ever do, pass everything to client
+ ForgeLogger.logServer( LogDirection.SENDING, this.name(), message);
+ con.unsafe().sendPacket(message);
return this;
}
}
diff --git a/proxy/src/main/java/net/md_5/bungee/module/ModuleManager.java b/proxy/src/main/java/net/md_5/bungee/module/ModuleManager.java
index 901fc5a37c..8c14590090 100644
--- a/proxy/src/main/java/net/md_5/bungee/module/ModuleManager.java
+++ b/proxy/src/main/java/net/md_5/bungee/module/ModuleManager.java
@@ -29,6 +29,7 @@ public class ModuleManager
public ModuleManager()
{
knownSources.put( "jenkins", new JenkinsModuleSource() );
+ knownSources.put( "travis-ci", new TravisCiModuleSource() );
}
@SuppressFBWarnings(
@@ -80,13 +81,13 @@ public void load(ProxyServer proxy, File moduleDirectory) throws Exception
switch ( version )
{
case 0:
- defaults.add( "jenkins://cmd_alert" );
- defaults.add( "jenkins://cmd_find" );
- defaults.add( "jenkins://cmd_list" );
- defaults.add( "jenkins://cmd_send" );
- defaults.add( "jenkins://cmd_server" );
+ defaults.add( "travis-ci://cmd_alert" );
+ defaults.add( "travis-ci://cmd_find" );
+ defaults.add( "travis-ci://cmd_list" );
+ defaults.add( "travis-ci://cmd_send" );
+ defaults.add( "travis-ci://cmd_server" );
case 1:
- defaults.add( "jenkins://reconnect_yaml" );
+ defaults.add( "travis-ci://reconnect_yaml" );
}
config.put( "modules", defaults );
config.put( "version", 2 );
diff --git a/proxy/src/main/java/net/md_5/bungee/module/TravisCiModuleSource.java b/proxy/src/main/java/net/md_5/bungee/module/TravisCiModuleSource.java
new file mode 100644
index 0000000000..fd40cf934c
--- /dev/null
+++ b/proxy/src/main/java/net/md_5/bungee/module/TravisCiModuleSource.java
@@ -0,0 +1,39 @@
+package net.md_5.bungee.module;
+
+
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLConnection;
+
+import com.google.common.io.ByteStreams;
+import com.google.common.io.Files;
+
+import lombok.Data;
+import net.md_5.bungee.Util;
+
+
+@Data
+public class TravisCiModuleSource implements ModuleSource
+{
+
+ @Override
+ public void retrieve(ModuleSpec module, ModuleVersion version)
+ {
+ System.out.println("Attempting to download Tracis-CI module " + module.getName() + " v" + version.getBuild());
+ try
+ {
+ URL website = new URL("https://github.com/HexagonMC/BungeeCord/releases/download/v" + version.getBuild() + "/" + module.getName() + ".jar");
+ URLConnection con = website.openConnection();
+ // 15 second timeout at various stages
+ con.setConnectTimeout(15000);
+ con.setReadTimeout(15000);
+
+ Files.write(ByteStreams.toByteArray(con.getInputStream()), module.getFile());
+ System.out.println("Download complete");
+ }
+ catch (IOException ex)
+ {
+ System.out.println("Failed to download: " + Util.exception(ex));
+ }
+ }
+}
diff --git a/proxy/src/main/java/net/md_5/bungee/tab/Global.java b/proxy/src/main/java/net/md_5/bungee/tab/Global.java
index 0cf1d21873..e164cabd62 100644
--- a/proxy/src/main/java/net/md_5/bungee/tab/Global.java
+++ b/proxy/src/main/java/net/md_5/bungee/tab/Global.java
@@ -6,6 +6,7 @@
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.chat.ComponentSerializer;
import net.md_5.bungee.connection.LoginResult;
+import net.md_5.bungee.protocol.ProtocolConstants;
import net.md_5.bungee.protocol.packet.PlayerListItem;
import java.util.Collection;
@@ -37,7 +38,7 @@ public void onPingChange(int ping)
PlayerListItem.Item item = new PlayerListItem.Item();
item.setUuid( player.getUniqueId() );
item.setUsername( player.getName() );
- item.setDisplayName( ComponentSerializer.toString( TextComponent.fromLegacyText( player.getDisplayName() ) ) );
+ item.setDisplayName( player.getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_8 ? ComponentSerializer.toString( TextComponent.fromLegacyText( player.getDisplayName() ) ) : player.getDisplayName() );
item.setPing( player.getPing() );
packet.setItems( new PlayerListItem.Item[]
{
@@ -67,7 +68,7 @@ public void onConnect()
PlayerListItem.Item item = items[i++] = new PlayerListItem.Item();
item.setUuid( p.getUniqueId() );
item.setUsername( p.getName() );
- item.setDisplayName( ComponentSerializer.toString( TextComponent.fromLegacyText( p.getDisplayName() ) ) );
+ item.setDisplayName( player.getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_8 ? ComponentSerializer.toString( TextComponent.fromLegacyText( p.getDisplayName() ) ) : p.getDisplayName() );
LoginResult loginResult = ( (UserConnection) p ).getPendingConnection().getLoginProfile();
if ( loginResult != null )
{
@@ -89,13 +90,30 @@ public void onConnect()
item.setGamemode( ( (UserConnection) p ).getGamemode() );
item.setPing( p.getPing() );
}
- player.unsafe().sendPacket( playerListItem );
+ if ( player.getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_8 )
+ {
+ player.unsafe().sendPacket( playerListItem );
+ } else
+ {
+ // Split up the packet
+ for ( PlayerListItem.Item item : playerListItem.getItems() )
+ {
+ PlayerListItem packet = new PlayerListItem();
+ packet.setAction( playerListItem.getAction() );
+
+ packet.setItems( new PlayerListItem.Item[]
+ {
+ item
+ } );
+ player.unsafe().sendPacket( packet );
+ }
+ }
PlayerListItem packet = new PlayerListItem();
packet.setAction( PlayerListItem.Action.ADD_PLAYER );
PlayerListItem.Item item = new PlayerListItem.Item();
item.setUuid( player.getUniqueId() );
item.setUsername( player.getName() );
- item.setDisplayName( ComponentSerializer.toString( TextComponent.fromLegacyText( player.getDisplayName() ) ) );
+ item.setDisplayName( player.getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_8 ? ComponentSerializer.toString( TextComponent.fromLegacyText( player.getDisplayName() ) ) : player.getDisplayName() );
LoginResult loginResult = ( (UserConnection) player ).getPendingConnection().getLoginProfile();
if ( loginResult != null )
{
diff --git a/proxy/src/main/java/net/md_5/bungee/tab/GlobalPing.java b/proxy/src/main/java/net/md_5/bungee/tab/GlobalPing.java
index fb4991c1d6..25ed37aeee 100644
--- a/proxy/src/main/java/net/md_5/bungee/tab/GlobalPing.java
+++ b/proxy/src/main/java/net/md_5/bungee/tab/GlobalPing.java
@@ -4,6 +4,7 @@
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.chat.ComponentSerializer;
+import net.md_5.bungee.protocol.ProtocolConstants;
import net.md_5.bungee.protocol.packet.PlayerListItem;
public class GlobalPing extends Global
@@ -29,7 +30,7 @@ public void onPingChange(int ping)
PlayerListItem.Item item = new PlayerListItem.Item();
item.setUuid( player.getUniqueId() );
item.setUsername( player.getName() );
- item.setDisplayName( ComponentSerializer.toString( TextComponent.fromLegacyText( player.getDisplayName() ) ) );
+ item.setDisplayName( player.getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_8 ? ComponentSerializer.toString( TextComponent.fromLegacyText( player.getDisplayName() ) ) : player.getDisplayName() );
item.setPing( player.getPing() );
packet.setItems( new PlayerListItem.Item[]
{
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 daf12f74e4..835a301ce8 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.HashSet;
import java.util.UUID;
import net.md_5.bungee.api.connection.ProxiedPlayer;
+import net.md_5.bungee.protocol.ProtocolConstants;
import net.md_5.bungee.protocol.packet.PlayerListItem;
public class ServerUnique extends TabList
{
private final Collection uuids = new HashSet<>();
+ private final Collection usernames = new HashSet<>(); // Support for <=1.7.9
public ServerUnique(ProxiedPlayer player)
{
@@ -23,10 +25,22 @@ public void onUpdate(PlayerListItem playerListItem)
{
if ( playerListItem.getAction() == PlayerListItem.Action.ADD_PLAYER )
{
- uuids.add( item.getUuid() );
+ if ( item.getUuid() != null )
+ {
+ uuids.add( item.getUuid() );
+ } else
+ {
+ usernames.add( item.getUsername() );
+ }
} else if ( playerListItem.getAction() == PlayerListItem.Action.REMOVE_PLAYER )
{
- uuids.remove( item.getUuid() );
+ if ( item.getUuid() != null )
+ {
+ uuids.remove( item.getUuid() );
+ } else
+ {
+ usernames.remove( item.getUsername() );
+ }
}
}
player.unsafe().sendPacket( playerListItem );
@@ -43,16 +57,40 @@ public void onServerChange()
{
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() ];
int i = 0;
for ( UUID uuid : uuids )
{
PlayerListItem.Item item = items[i++] = new PlayerListItem.Item();
item.setUuid( uuid );
}
+ for ( String username : usernames )
+ {
+ PlayerListItem.Item item = items[i++] = new PlayerListItem.Item();
+ item.setUsername( username );
+ item.setDisplayName( username );
+ }
packet.setItems( items );
- player.unsafe().sendPacket( packet );
+ if ( 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 );
+ }
+ }
uuids.clear();
+ usernames.clear();
}
@Override
diff --git a/proxy/src/main/java/net/md_5/bungee/tab/TabList.java b/proxy/src/main/java/net/md_5/bungee/tab/TabList.java
index 7b59c75722..29f2a7ddce 100644
--- a/proxy/src/main/java/net/md_5/bungee/tab/TabList.java
+++ b/proxy/src/main/java/net/md_5/bungee/tab/TabList.java
@@ -3,8 +3,11 @@
import lombok.RequiredArgsConstructor;
import net.md_5.bungee.BungeeCord;
import net.md_5.bungee.UserConnection;
+import net.md_5.bungee.api.chat.BaseComponent;
+import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.connection.LoginResult;
+import net.md_5.bungee.protocol.ProtocolConstants;
import net.md_5.bungee.protocol.packet.PlayerListItem;
@RequiredArgsConstructor
diff --git a/query/src/main/java/net/md_5/bungee/query/QueryHandler.java b/query/src/main/java/net/md_5/bungee/query/QueryHandler.java
index 79d6886a60..4ac87e7d88 100644
--- a/query/src/main/java/net/md_5/bungee/query/QueryHandler.java
+++ b/query/src/main/java/net/md_5/bungee/query/QueryHandler.java
@@ -110,7 +110,7 @@ protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket msg) throw
data.put( "gametype", "SMP" );
// Start Extra Info
data.put( "game_id", "MINECRAFT" );
- data.put( "version", bungee.getGameVersion() );
+ data.put( "version", bungee.getConfig().getCustomServerName() + " " + bungee.getGameVersion() );
data.put( "plugins", "" );
// End Extra Info
data.put( "map", "BungeeCord_Proxy" );