diff --git a/api/src/main/java/net/md_5/bungee/Util.java b/api/src/main/java/net/md_5/bungee/Util.java index cb84917ee6..5e5b53a706 100644 --- a/api/src/main/java/net/md_5/bungee/Util.java +++ b/api/src/main/java/net/md_5/bungee/Util.java @@ -29,7 +29,12 @@ public static InetSocketAddress getAddr(String hostline) uri = new URI( "tcp://" + hostline ); } catch ( URISyntaxException ex ) { - throw new IllegalArgumentException( "Bad hostline", ex ); + throw new IllegalArgumentException( "Bad hostline: " + hostline, ex ); + } + + if ( uri.getHost() == null ) + { + throw new IllegalArgumentException( "Invalid host/address: " + hostline ); } return new InetSocketAddress( uri.getHost(), ( uri.getPort() ) == -1 ? DEFAULT_PORT : uri.getPort() ); diff --git a/api/src/main/java/net/md_5/bungee/api/config/ServerInfo.java b/api/src/main/java/net/md_5/bungee/api/config/ServerInfo.java index 7b7c987f0e..1977384330 100644 --- a/api/src/main/java/net/md_5/bungee/api/config/ServerInfo.java +++ b/api/src/main/java/net/md_5/bungee/api/config/ServerInfo.java @@ -43,6 +43,22 @@ public interface ServerInfo */ String getMotd(); + /** + * Whether this server is restricted and therefore only players with the + * given permission can access it. + * + * @return if restricted + */ + boolean isRestricted(); + + /** + * Get the permission required to access this server. Only enforced when the + * server is restricted. + * + * @return access permission + */ + String getPermission(); + /** * Whether the player can access this server. It will only return false when * the player has no permission and this server is restricted. diff --git a/api/src/main/java/net/md_5/bungee/api/connection/ProxiedPlayer.java b/api/src/main/java/net/md_5/bungee/api/connection/ProxiedPlayer.java index e3e999b0db..867e4428ef 100644 --- a/api/src/main/java/net/md_5/bungee/api/connection/ProxiedPlayer.java +++ b/api/src/main/java/net/md_5/bungee/api/connection/ProxiedPlayer.java @@ -107,7 +107,7 @@ public enum MainHand * @param target the new server to connect to * @param callback the method called when the connection is complete, or * when an exception is encountered. The boolean parameter denotes success - * or failure. + * (true) or failure (false). */ void connect(ServerInfo target, Callback callback); @@ -119,7 +119,7 @@ public enum MainHand * @param target the new server to connect to * @param callback the method called when the connection is complete, or * when an exception is encountered. The boolean parameter denotes success - * or failure. + * (true) or failure (false). * @param reason the reason for connecting to the new server */ void connect(ServerInfo target, Callback callback, ServerConnectEvent.Reason reason); diff --git a/api/src/main/java/net/md_5/bungee/api/event/AsyncEvent.java b/api/src/main/java/net/md_5/bungee/api/event/AsyncEvent.java index 050da40305..cf85ca06d7 100644 --- a/api/src/main/java/net/md_5/bungee/api/event/AsyncEvent.java +++ b/api/src/main/java/net/md_5/bungee/api/event/AsyncEvent.java @@ -1,13 +1,14 @@ package net.md_5.bungee.api.event; import com.google.common.base.Preconditions; -import java.util.Collections; -import java.util.Set; +import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; +import lombok.AccessLevel; import lombok.Data; import lombok.EqualsAndHashCode; +import lombok.Getter; import lombok.ToString; import net.md_5.bungee.api.Callback; import net.md_5.bungee.api.plugin.Event; @@ -19,13 +20,14 @@ * @param Type of this event */ @Data +@Getter(AccessLevel.NONE) @ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) public class AsyncEvent extends Event { private final Callback done; - private final Set intents = Collections.newSetFromMap( new ConcurrentHashMap() ); + private final Map intents = new ConcurrentHashMap<>(); private final AtomicBoolean fired = new AtomicBoolean(); private final AtomicInteger latch = new AtomicInteger(); @@ -43,30 +45,40 @@ public void postCall() /** * Register an intent that this plugin will continue to perform work on a * background task, and wishes to let the event proceed once the registered - * background task has completed. + * background task has completed. Multiple intents can be registered by a + * plugin, but the plugin must complete the same amount of intents for the + * event to proceed. * * @param plugin the plugin registering this intent */ public void registerIntent(Plugin plugin) { Preconditions.checkState( !fired.get(), "Event %s has already been fired", this ); - Preconditions.checkState( !intents.contains( plugin ), "Plugin %s already registered intent for event %s", plugin, this ); - intents.add( plugin ); + AtomicInteger intentCount = intents.get( plugin ); + if ( intentCount == null ) + { + intents.put( plugin, new AtomicInteger( 1 ) ); + } else + { + intentCount.incrementAndGet(); + } latch.incrementAndGet(); } /** - * Notifies this event that this plugin has done all its required processing - * and wishes to let the event proceed. + * Notifies this event that this plugin has completed an intent and wishes + * to let the event proceed once all intents have been completed. * * @param plugin a plugin which has an intent registered for this event */ @SuppressWarnings("unchecked") public void completeIntent(Plugin plugin) { - Preconditions.checkState( intents.contains( plugin ), "Plugin %s has not registered intent for event %s", plugin, this ); - intents.remove( plugin ); + AtomicInteger intentCount = intents.get( plugin ); + Preconditions.checkState( intentCount != null && intentCount.get() > 0, "Plugin %s has not registered intents for event %s", plugin, this ); + + intentCount.decrementAndGet(); if ( fired.get() ) { if ( latch.decrementAndGet() == 0 ) diff --git a/api/src/main/java/net/md_5/bungee/api/event/ChatEvent.java b/api/src/main/java/net/md_5/bungee/api/event/ChatEvent.java index 067a800cf4..828ede5646 100644 --- a/api/src/main/java/net/md_5/bungee/api/event/ChatEvent.java +++ b/api/src/main/java/net/md_5/bungee/api/event/ChatEvent.java @@ -3,8 +3,11 @@ import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; +import net.md_5.bungee.api.CommandSender; +import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.connection.Connection; import net.md_5.bungee.api.plugin.Cancellable; +import net.md_5.bungee.api.plugin.PluginManager; /** * Event called when a player sends a message to a server. @@ -39,4 +42,25 @@ public boolean isCommand() { return message.length() > 0 && message.charAt( 0 ) == '/'; } + + /** + * Checks whether this message is run on this proxy server. + * + * @return if this command runs on the proxy + * @see PluginManager#isExecutableCommand(java.lang.String, + * net.md_5.bungee.api.CommandSender) + */ + public boolean isProxyCommand() + { + if ( !isCommand() ) + { + return false; + } + + int index = message.indexOf( " " ); + String commandName = ( index == -1 ) ? message.substring( 1 ) : message.substring( 1, index ); + CommandSender sender = ( getSender() instanceof CommandSender ) ? (CommandSender) getSender() : null; + + return ProxyServer.getInstance().getPluginManager().isExecutableCommand( commandName, sender ); + } } diff --git a/api/src/main/java/net/md_5/bungee/api/plugin/PluginManager.java b/api/src/main/java/net/md_5/bungee/api/plugin/PluginManager.java index 3a871787f8..bf894e4a21 100644 --- a/api/src/main/java/net/md_5/bungee/api/plugin/PluginManager.java +++ b/api/src/main/java/net/md_5/bungee/api/plugin/PluginManager.java @@ -111,6 +111,32 @@ public void unregisterCommands(Plugin plugin) } } + private Command getCommandIfEnabled(String commandName, CommandSender sender) + { + String commandLower = commandName.toLowerCase( Locale.ROOT ); + + // Check if command is disabled when a player sent the command + if ( ( sender instanceof ProxiedPlayer ) && proxy.getDisabledCommands().contains( commandLower ) ) + { + return null; + } + + return commandMap.get( commandLower ); + } + + /** + * Checks if the command is registered and can possibly be executed by the + * sender (without taking permissions into account). + * + * @param commandName the name of the command + * @param sender the sender executing the command + * @return whether the command will be handled + */ + public boolean isExecutableCommand(String commandName, CommandSender sender) + { + return getCommandIfEnabled( commandName, sender ) != null; + } + public boolean dispatchCommand(CommandSender sender, String commandLine) { return dispatchCommand( sender, commandLine, null ); @@ -133,12 +159,7 @@ public boolean dispatchCommand(CommandSender sender, String commandLine, List() ); + ComponentSerializer.serializedComponents.set( Collections.newSetFromMap( new IdentityHashMap() ) ); } try { diff --git a/chat/src/main/java/net/md_5/bungee/chat/ComponentSerializer.java b/chat/src/main/java/net/md_5/bungee/chat/ComponentSerializer.java index 0b7cf3b499..eaf9f79fd0 100644 --- a/chat/src/main/java/net/md_5/bungee/chat/ComponentSerializer.java +++ b/chat/src/main/java/net/md_5/bungee/chat/ComponentSerializer.java @@ -16,7 +16,7 @@ import net.md_5.bungee.api.chat.TranslatableComponent; import java.lang.reflect.Type; -import java.util.HashSet; +import java.util.Set; public class ComponentSerializer implements JsonDeserializer { @@ -31,7 +31,7 @@ public class ComponentSerializer implements JsonDeserializer registerTypeAdapter( SelectorComponent.class, new SelectorComponentSerializer() ). create(); - public final static ThreadLocal> serializedComponents = new ThreadLocal>(); + public final static ThreadLocal> serializedComponents = new ThreadLocal>(); public static BaseComponent[] parse(String json) { diff --git a/chat/src/main/java/net/md_5/bungee/chat/ScoreComponentSerializer.java b/chat/src/main/java/net/md_5/bungee/chat/ScoreComponentSerializer.java index ecff9beffa..f09c8bf900 100644 --- a/chat/src/main/java/net/md_5/bungee/chat/ScoreComponentSerializer.java +++ b/chat/src/main/java/net/md_5/bungee/chat/ScoreComponentSerializer.java @@ -17,17 +17,18 @@ public class ScoreComponentSerializer extends BaseComponentSerializer implements public ScoreComponent deserialize(JsonElement element, Type type, JsonDeserializationContext context) throws JsonParseException { JsonObject json = element.getAsJsonObject(); - if ( !json.has( "name" ) || !json.has( "objective" ) ) + JsonObject score = json.get( "score" ).getAsJsonObject(); + if ( !score.has( "name" ) || !score.has( "objective" ) ) { throw new JsonParseException( "A score component needs at least a name and an objective" ); } - String name = json.get( "name" ).getAsString(); - String objective = json.get( "objective" ).getAsString(); + String name = score.get( "name" ).getAsString(); + String objective = score.get( "objective" ).getAsString(); ScoreComponent component = new ScoreComponent( name, objective ); - if ( json.has( "value" ) && !json.get( "value" ).getAsString().isEmpty() ) + if ( score.has( "value" ) && !score.get( "value" ).getAsString().isEmpty() ) { - component.setValue( json.get( "value" ).getAsString() ); + component.setValue( score.get( "value" ).getAsString() ); } deserialize( json, component, context ); diff --git a/chat/src/test/java/net/md_5/bungee/api/chat/ComponentsTest.java b/chat/src/test/java/net/md_5/bungee/api/chat/ComponentsTest.java index 27b5bbeaf9..8fa10e4433 100644 --- a/chat/src/test/java/net/md_5/bungee/api/chat/ComponentsTest.java +++ b/chat/src/test/java/net/md_5/bungee/api/chat/ComponentsTest.java @@ -75,6 +75,16 @@ public void testBuilderAppendMixedComponents() Assert.assertEquals( scoreComponent.toPlainText(), components[3].toPlainText() ); } + @Test + public void testScore() + { + BaseComponent[] component = ComponentSerializer.parse( "{\"score\":{\"name\":\"@p\",\"objective\":\"TEST\",\"value\":\"hello\"}}" ); + String text = ComponentSerializer.toString( component ); + BaseComponent[] reparsed = ComponentSerializer.parse( text ); + + Assert.assertArrayEquals( component, reparsed ); + } + @Test public void testBuilderAppend() { @@ -92,6 +102,18 @@ public void testBuilderAppend() Assert.assertEquals( ChatColor.YELLOW + "Hello " + ChatColor.GREEN + "world!", BaseComponent.toLegacyText( components ) ); } + @Test + public void testBuilderAppendLegacy() + { + ComponentBuilder builder = new ComponentBuilder( "Hello " ).color( ChatColor.YELLOW ); + builder.appendLegacy( "§aworld!" ); + + BaseComponent[] components = builder.create(); + + Assert.assertEquals( "Hello world!", BaseComponent.toPlainText( components ) ); + Assert.assertEquals( ChatColor.YELLOW + "Hello " + ChatColor.GREEN + "world!", BaseComponent.toLegacyText( components ) ); + } + @Test public void testBasicComponent() { diff --git a/module/cmd-alert/src/main/java/net/md_5/bungee/module/cmd/alert/CommandAlertRaw.java b/module/cmd-alert/src/main/java/net/md_5/bungee/module/cmd/alert/CommandAlertRaw.java index 24da97b6a2..4d4ef1be0a 100644 --- a/module/cmd-alert/src/main/java/net/md_5/bungee/module/cmd/alert/CommandAlertRaw.java +++ b/module/cmd-alert/src/main/java/net/md_5/bungee/module/cmd/alert/CommandAlertRaw.java @@ -40,11 +40,12 @@ public void execute(CommandSender sender, String[] args) } if ( sender instanceof ProxiedPlayer ) { - sender.sendMessage( - new ComponentBuilder( "An error occurred while parsing your message. (Hover for details)" ). - color( ChatColor.RED ).underlined( true ). - event( new HoverEvent( HoverEvent.Action.SHOW_TEXT, new ComponentBuilder( error.getMessage() ).color( ChatColor.RED ).create() ) ). - create() ); + sender.sendMessage( new ComponentBuilder( "An error occurred while parsing your message. (Hover for details)" ) + .color( ChatColor.RED ) + .underlined( true ) + .event( new HoverEvent( HoverEvent.Action.SHOW_TEXT, new ComponentBuilder( error.getMessage() ).color( ChatColor.RED ).create() ) ) + .create() + ); } else { sender.sendMessage( new ComponentBuilder( "An error occurred while parsing your message: " ).color( ChatColor.RED ).append( error.getMessage() ).create() ); diff --git a/module/cmd-server/src/main/java/net/md_5/bungee/module/cmd/server/CommandServer.java b/module/cmd-server/src/main/java/net/md_5/bungee/module/cmd/server/CommandServer.java index ebf9a12dcb..794d571fe7 100644 --- a/module/cmd-server/src/main/java/net/md_5/bungee/module/cmd/server/CommandServer.java +++ b/module/cmd-server/src/main/java/net/md_5/bungee/module/cmd/server/CommandServer.java @@ -49,10 +49,10 @@ public void execute(CommandSender sender, String[] args) { TextComponent serverTextComponent = new TextComponent( first ? server.getName() : ", " + server.getName() ); int count = server.getPlayers().size(); - serverTextComponent.setHoverEvent( new HoverEvent( HoverEvent.Action.SHOW_TEXT, - new ComponentBuilder( count + ( count == 1 ? " player" : " players" ) + "\n" ) - .append( "Click to connect to the server" ).italic( true ) - .create() ) ); + serverTextComponent.setHoverEvent( new HoverEvent( + HoverEvent.Action.SHOW_TEXT, + new ComponentBuilder( count + ( count == 1 ? " player" : " players" ) + "\n" ).append( "Click to connect to the server" ).italic( true ).create() ) + ); serverTextComponent.setClickEvent( new ClickEvent( ClickEvent.Action.RUN_COMMAND, "/server " + server.getName() ) ); serverList.append( serverTextComponent ); first = false; diff --git a/pom.xml b/pom.xml index ef6575a2ef..10710ba813 100644 --- a/pom.xml +++ b/pom.xml @@ -73,7 +73,7 @@ unknown - 4.1.32.Final + 4.1.34.Final 1.7 1.7 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 27bf6dacb3..659a694de7 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 @@ -7,10 +7,8 @@ import gnu.trove.map.hash.TIntObjectHashMap; import gnu.trove.map.hash.TObjectIntHashMap; import java.lang.reflect.Constructor; -import java.util.Arrays; -import java.util.List; +import lombok.Data; import lombok.Getter; -import lombok.RequiredArgsConstructor; import net.md_5.bungee.protocol.packet.BossBar; import net.md_5.bungee.protocol.packet.Chat; import net.md_5.bungee.protocol.packet.ClientSettings; @@ -52,7 +50,7 @@ public enum Protocol { TO_SERVER.registerPacket( Handshake.class, - map( ProtocolConstants.MINECRAFT_1_8, 0x00 ) + map( ProtocolConstants.MINECRAFT_1_7_2, 0x00 ) ); } }, @@ -63,28 +61,25 @@ public enum Protocol { TO_CLIENT.registerPacket( KeepAlive.class, - map( ProtocolConstants.MINECRAFT_1_8, 0x00 ), + map( ProtocolConstants.MINECRAFT_1_7_2, 0x00 ), map( ProtocolConstants.MINECRAFT_1_9, 0x1F ), - map( ProtocolConstants.MINECRAFT_1_12, 0x1F ), map( ProtocolConstants.MINECRAFT_1_13, 0x21 ) ); TO_CLIENT.registerPacket( Login.class, - map( ProtocolConstants.MINECRAFT_1_8, 0x01 ), + map( ProtocolConstants.MINECRAFT_1_7_2, 0x01 ), map( ProtocolConstants.MINECRAFT_1_9, 0x23 ), - map( ProtocolConstants.MINECRAFT_1_12, 0x23 ), map( ProtocolConstants.MINECRAFT_1_13, 0x25 ) ); TO_CLIENT.registerPacket( Chat.class, - map( ProtocolConstants.MINECRAFT_1_8, 0x02 ), + map( ProtocolConstants.MINECRAFT_1_7_2, 0x02 ), map( ProtocolConstants.MINECRAFT_1_9, 0x0F ), - map( ProtocolConstants.MINECRAFT_1_12, 0x0F ), map( ProtocolConstants.MINECRAFT_1_13, 0x0E ) ); TO_CLIENT.registerPacket( Respawn.class, - map( ProtocolConstants.MINECRAFT_1_8, 0x07 ), + map( ProtocolConstants.MINECRAFT_1_7_2, 0x07 ), map( ProtocolConstants.MINECRAFT_1_9, 0x33 ), map( ProtocolConstants.MINECRAFT_1_12, 0x34 ), map( ProtocolConstants.MINECRAFT_1_12_1, 0x35 ), @@ -92,28 +87,24 @@ public enum Protocol ); TO_CLIENT.registerPacket( BossBar.class, - map( ProtocolConstants.MINECRAFT_1_9, 0x0C ), - map( ProtocolConstants.MINECRAFT_1_12, 0x0C ), - map( ProtocolConstants.MINECRAFT_1_13, 0x0C ) + map( ProtocolConstants.MINECRAFT_1_9, 0x0C ) ); TO_CLIENT.registerPacket( PlayerListItem.class, // PlayerInfo - map( ProtocolConstants.MINECRAFT_1_8, 0x38 ), + map( ProtocolConstants.MINECRAFT_1_7_2, 0x38 ), map( ProtocolConstants.MINECRAFT_1_9, 0x2D ), - map( ProtocolConstants.MINECRAFT_1_12, 0x2D ), map( ProtocolConstants.MINECRAFT_1_12_1, 0x2E ), map( ProtocolConstants.MINECRAFT_1_13, 0x30 ) ); TO_CLIENT.registerPacket( TabCompleteResponse.class, - map( ProtocolConstants.MINECRAFT_1_8, 0x3A ), + map( ProtocolConstants.MINECRAFT_1_7_2, 0x3A ), map( ProtocolConstants.MINECRAFT_1_9, 0x0E ), - map( ProtocolConstants.MINECRAFT_1_12, 0x0E ), map( ProtocolConstants.MINECRAFT_1_13, 0x10 ) ); TO_CLIENT.registerPacket( ScoreboardObjective.class, - map( ProtocolConstants.MINECRAFT_1_8, 0x3B ), + map( ProtocolConstants.MINECRAFT_1_7_2, 0x3B ), map( ProtocolConstants.MINECRAFT_1_9, 0x3F ), map( ProtocolConstants.MINECRAFT_1_12, 0x41 ), map( ProtocolConstants.MINECRAFT_1_12_1, 0x42 ), @@ -121,7 +112,7 @@ public enum Protocol ); TO_CLIENT.registerPacket( ScoreboardScore.class, - map( ProtocolConstants.MINECRAFT_1_8, 0x3C ), + map( ProtocolConstants.MINECRAFT_1_7_2, 0x3C ), map( ProtocolConstants.MINECRAFT_1_9, 0x42 ), map( ProtocolConstants.MINECRAFT_1_12, 0x44 ), map( ProtocolConstants.MINECRAFT_1_12_1, 0x45 ), @@ -129,7 +120,7 @@ public enum Protocol ); TO_CLIENT.registerPacket( ScoreboardDisplay.class, - map( ProtocolConstants.MINECRAFT_1_8, 0x3D ), + map( ProtocolConstants.MINECRAFT_1_7_2, 0x3D ), map( ProtocolConstants.MINECRAFT_1_9, 0x38 ), map( ProtocolConstants.MINECRAFT_1_12, 0x3A ), map( ProtocolConstants.MINECRAFT_1_12_1, 0x3B ), @@ -137,7 +128,7 @@ public enum Protocol ); TO_CLIENT.registerPacket( Team.class, - map( ProtocolConstants.MINECRAFT_1_8, 0x3E ), + map( ProtocolConstants.MINECRAFT_1_7_2, 0x3E ), map( ProtocolConstants.MINECRAFT_1_9, 0x41 ), map( ProtocolConstants.MINECRAFT_1_12, 0x43 ), map( ProtocolConstants.MINECRAFT_1_12_1, 0x44 ), @@ -145,16 +136,14 @@ public enum Protocol ); TO_CLIENT.registerPacket( PluginMessage.class, - map( ProtocolConstants.MINECRAFT_1_8, 0x3F ), + map( ProtocolConstants.MINECRAFT_1_7_2, 0x3F ), map( ProtocolConstants.MINECRAFT_1_9, 0x18 ), - map( ProtocolConstants.MINECRAFT_1_12, 0x18 ), map( ProtocolConstants.MINECRAFT_1_13, 0x19 ) ); TO_CLIENT.registerPacket( Kick.class, - map( ProtocolConstants.MINECRAFT_1_8, 0x40 ), + map( ProtocolConstants.MINECRAFT_1_7_2, 0x40 ), map( ProtocolConstants.MINECRAFT_1_9, 0x1A ), - map( ProtocolConstants.MINECRAFT_1_12, 0x1A ), map( ProtocolConstants.MINECRAFT_1_13, 0x1B ) ); TO_CLIENT.registerPacket( @@ -173,30 +162,20 @@ public enum Protocol map( ProtocolConstants.MINECRAFT_1_12_1, 0x4A ), map( ProtocolConstants.MINECRAFT_1_13, 0x4E ) ); - 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_CLIENT.registerPacket( EntityStatus.class, map( ProtocolConstants.MINECRAFT_1_8, 0x1A ), map( ProtocolConstants.MINECRAFT_1_9, 0x1B ), - map( ProtocolConstants.MINECRAFT_1_12, 0x1B ), map( ProtocolConstants.MINECRAFT_1_13, 0x1C ) ); - if ( Boolean.getBoolean( "net.md-5.bungee.protocol.register_commands" ) ) - { - TO_CLIENT.registerPacket( - Commands.class, - map( ProtocolConstants.MINECRAFT_1_13, 0x11 ) - ); - } + TO_CLIENT.registerPacket( + Commands.class, + map( ProtocolConstants.MINECRAFT_1_13, 0x11 ) + ); TO_SERVER.registerPacket( KeepAlive.class, - map( ProtocolConstants.MINECRAFT_1_8, 0x00 ), + map( ProtocolConstants.MINECRAFT_1_7_2, 0x00 ), map( ProtocolConstants.MINECRAFT_1_9, 0x0B ), map( ProtocolConstants.MINECRAFT_1_12, 0x0C ), map( ProtocolConstants.MINECRAFT_1_12_1, 0x0B ), @@ -204,15 +183,14 @@ public enum Protocol ); TO_SERVER.registerPacket( Chat.class, - map( ProtocolConstants.MINECRAFT_1_8, 0x01 ), + map( ProtocolConstants.MINECRAFT_1_7_2, 0x01 ), map( ProtocolConstants.MINECRAFT_1_9, 0x02 ), map( ProtocolConstants.MINECRAFT_1_12, 0x03 ), - map( ProtocolConstants.MINECRAFT_1_12_1, 0x02 ), - map( ProtocolConstants.MINECRAFT_1_13, 0x02 ) + map( ProtocolConstants.MINECRAFT_1_12_1, 0x02 ) ); TO_SERVER.registerPacket( TabCompleteRequest.class, - map( ProtocolConstants.MINECRAFT_1_8, 0x14 ), + map( ProtocolConstants.MINECRAFT_1_7_2, 0x14 ), map( ProtocolConstants.MINECRAFT_1_9, 0x01 ), map( ProtocolConstants.MINECRAFT_1_12, 0x02 ), map( ProtocolConstants.MINECRAFT_1_12_1, 0x01 ), @@ -220,15 +198,14 @@ public enum Protocol ); TO_SERVER.registerPacket( ClientSettings.class, - map( ProtocolConstants.MINECRAFT_1_8, 0x15 ), + map( ProtocolConstants.MINECRAFT_1_7_2, 0x15 ), map( ProtocolConstants.MINECRAFT_1_9, 0x04 ), map( ProtocolConstants.MINECRAFT_1_12, 0x05 ), - map( ProtocolConstants.MINECRAFT_1_12_1, 0x04 ), - map( ProtocolConstants.MINECRAFT_1_13, 0x04 ) + map( ProtocolConstants.MINECRAFT_1_12_1, 0x04 ) ); TO_SERVER.registerPacket( PluginMessage.class, - map( ProtocolConstants.MINECRAFT_1_8, 0x17 ), + map( ProtocolConstants.MINECRAFT_1_7_2, 0x17 ), map( ProtocolConstants.MINECRAFT_1_9, 0x09 ), map( ProtocolConstants.MINECRAFT_1_12, 0x0A ), map( ProtocolConstants.MINECRAFT_1_12_1, 0x09 ), @@ -243,20 +220,20 @@ public enum Protocol { TO_CLIENT.registerPacket( StatusResponse.class, - map( ProtocolConstants.MINECRAFT_1_8, 0x00 ) + map( ProtocolConstants.MINECRAFT_1_7_2, 0x00 ) ); TO_CLIENT.registerPacket( PingPacket.class, - map( ProtocolConstants.MINECRAFT_1_8, 0x01 ) + map( ProtocolConstants.MINECRAFT_1_7_2, 0x01 ) ); TO_SERVER.registerPacket( StatusRequest.class, - map( ProtocolConstants.MINECRAFT_1_8, 0x00 ) + map( ProtocolConstants.MINECRAFT_1_7_2, 0x00 ) ); TO_SERVER.registerPacket( PingPacket.class, - map( ProtocolConstants.MINECRAFT_1_8, 0x01 ) + map( ProtocolConstants.MINECRAFT_1_7_2, 0x01 ) ); } }, @@ -267,15 +244,15 @@ public enum Protocol { TO_CLIENT.registerPacket( Kick.class, - map( ProtocolConstants.MINECRAFT_1_8, 0x00 ) + map( ProtocolConstants.MINECRAFT_1_7_2, 0x00 ) ); TO_CLIENT.registerPacket( EncryptionRequest.class, - map( ProtocolConstants.MINECRAFT_1_8, 0x01 ) + map( ProtocolConstants.MINECRAFT_1_7_2, 0x01 ) ); TO_CLIENT.registerPacket( LoginSuccess.class, - map( ProtocolConstants.MINECRAFT_1_8, 0x02 ) + map( ProtocolConstants.MINECRAFT_1_7_2, 0x02 ) ); TO_CLIENT.registerPacket( SetCompression.class, @@ -288,11 +265,11 @@ public enum Protocol TO_SERVER.registerPacket( LoginRequest.class, - map( ProtocolConstants.MINECRAFT_1_8, 0x00 ) + map( ProtocolConstants.MINECRAFT_1_7_2, 0x00 ) ); TO_SERVER.registerPacket( EncryptionResponse.class, - map( ProtocolConstants.MINECRAFT_1_8, 0x01 ) + map( ProtocolConstants.MINECRAFT_1_7_2, 0x01 ) ); TO_SERVER.registerPacket( LoginPayloadResponse.class, @@ -303,8 +280,8 @@ public enum Protocol /*========================================================================*/ public static final int MAX_PACKET_ID = 0xFF; /*========================================================================*/ - public final DirectionData TO_SERVER = new DirectionData( this, ProtocolConstants.Direction.TO_SERVER ); - public final DirectionData TO_CLIENT = new DirectionData( this, ProtocolConstants.Direction.TO_CLIENT ); + final DirectionData TO_SERVER = new DirectionData( this, ProtocolConstants.Direction.TO_SERVER ); + final DirectionData TO_CLIENT = new DirectionData( this, ProtocolConstants.Direction.TO_CLIENT ); public static void main(String[] args) { @@ -340,80 +317,48 @@ private static void dump(int version, DirectionData data) } } - @RequiredArgsConstructor + @Data private static class ProtocolData { private final int protocolVersion; private final TObjectIntMap> packetMap = new TObjectIntHashMap<>( MAX_PACKET_ID ); - private final TIntObjectMap> packetConstructors = new TIntObjectHashMap<>( MAX_PACKET_ID ); + private final Constructor[] packetConstructors = new Constructor[ MAX_PACKET_ID ]; } - @RequiredArgsConstructor + @Data 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 map(protocol, id, true); - } - - private static ProtocolMapping map(int protocol, int id, boolean inherit) { - return new ProtocolMapping(protocol, id, inherit); + private static ProtocolMapping map(int protocol, int id) + { + return new ProtocolMapping(protocol, id); } - @RequiredArgsConstructor - public static class DirectionData + static final class DirectionData { - private final Protocol protocolPhase; private final TIntObjectMap protocols = new TIntObjectHashMap<>(); + // + private final Protocol protocolPhase; + @Getter + private final ProtocolConstants.Direction direction; + + public DirectionData(Protocol protocolPhase, ProtocolConstants.Direction direction) { + this.protocolPhase = protocolPhase; + this.direction = direction; + for ( int protocol : ProtocolConstants.SUPPORTED_VERSION_IDS ) { protocols.put( protocol, new ProtocolData( protocol ) ); } } - 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, - ProtocolConstants.MINECRAFT_1_13 - ) ); - linkedProtocols.put( ProtocolConstants.MINECRAFT_1_9, Arrays.asList( - ProtocolConstants.MINECRAFT_1_9_1, - ProtocolConstants.MINECRAFT_1_9_2, - ProtocolConstants.MINECRAFT_1_9_4 - ) ); - linkedProtocols.put( ProtocolConstants.MINECRAFT_1_9_4, Arrays.asList( - ProtocolConstants.MINECRAFT_1_10, - ProtocolConstants.MINECRAFT_1_11, - ProtocolConstants.MINECRAFT_1_11_1 - ) ); - linkedProtocols.put( ProtocolConstants.MINECRAFT_1_12, Arrays.asList( - ProtocolConstants.MINECRAFT_1_12_1 - ) ); - linkedProtocols.put( ProtocolConstants.MINECRAFT_1_12_1, Arrays.asList( - ProtocolConstants.MINECRAFT_1_12_2 - ) ); - linkedProtocols.put( ProtocolConstants.MINECRAFT_1_13, Arrays.asList( - ProtocolConstants.MINECRAFT_1_13_1, - ProtocolConstants.MINECRAFT_1_13_2 - ) ); - } - - @Getter - private final ProtocolConstants.Direction direction; private ProtocolData getProtocolData(int version) { @@ -430,14 +375,14 @@ public final DefinedPacket createPacket(int id, int version) ProtocolData protocolData = getProtocolData( version ); if ( protocolData == null ) { - throw new BadPacketException( "Unsupported protocol version" ); + throw new BadPacketException( "Unsupported protocol version " + version ); } if ( id > MAX_PACKET_ID ) { throw new BadPacketException( "Packet with id " + id + " outside of range " ); } - Constructor constructor = protocolData.packetConstructors.get( id ); + Constructor constructor = protocolData.packetConstructors[id]; try { return ( constructor == null ) ? null : constructor.newInstance(); @@ -447,36 +392,38 @@ public final DefinedPacket createPacket(int id, int version) } } - protected final void registerPacket(Class packetClass, ProtocolMapping... mappings) + private void registerPacket(Class packetClass, ProtocolMapping... mappings) { try { Constructor constructor = packetClass.getDeclaredConstructor(); - for ( ProtocolMapping mapping : mappings ) + + int mappingIndex = 0; + ProtocolMapping mapping = mappings[mappingIndex]; + for ( int protocol : ProtocolConstants.SUPPORTED_VERSION_IDS ) { - ProtocolData data = protocols.get( mapping.protocolVersion ); - data.packetMap.put( packetClass, mapping.packetID ); - data.packetConstructors.put( mapping.packetID, constructor ); + if ( protocol < mapping.protocolVersion ) + { + // This is a new packet, skip it till we reach the next protocol + continue; + } - if (mapping.inherit) + if ( mapping.protocolVersion < protocol && mappingIndex + 1 < mappings.length ) { - List links = linkedProtocols.get( mapping.protocolVersion ); - if ( links != null ) + // Mapping is non current, but the next one may be ok + ProtocolMapping nextMapping = mappings[mappingIndex + 1]; + if ( nextMapping.protocolVersion == protocol ) { - links: for ( int link : 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 ) ); - } + Preconditions.checkState( nextMapping.packetID != mapping.packetID, "Duplicate packet mapping (%s, %s)", mapping.protocolVersion, nextMapping.protocolVersion ); + + mapping = nextMapping; + mappingIndex++; } } + + ProtocolData data = protocols.get( protocol ); + data.packetMap.put( packetClass, mapping.packetID ); + data.packetConstructors[mapping.packetID] = constructor; } } catch ( NoSuchMethodException ex ) { 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 867a0f24ad..b43e2cc48b 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 @@ -31,7 +31,7 @@ public class ProtocolConstants "1.13.x" ); - public static final List SUPPORTED_VERSION_IDS = Arrays.asList( + public static final List SUPPORTED_VERSION_IDS = Arrays.asList( ProtocolConstants.MINECRAFT_1_7_2, ProtocolConstants.MINECRAFT_1_7_6, ProtocolConstants.MINECRAFT_1_8, diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/packet/TabCompleteResponse.java b/protocol/src/main/java/net/md_5/bungee/protocol/packet/TabCompleteResponse.java index 64851ddeae..79384bf5f3 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/packet/TabCompleteResponse.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/packet/TabCompleteResponse.java @@ -78,8 +78,8 @@ public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protoc for ( Suggestion suggestion : suggestions.getList() ) { writeString( suggestion.getText(), buf ); - buf.writeBoolean( suggestion.getTooltip() != null ); - if ( suggestion.getTooltip() != null ) + buf.writeBoolean( suggestion.getTooltip() != null && suggestion.getTooltip().getString() != null ); + if ( suggestion.getTooltip() != null && suggestion.getTooltip().getString() != null ) { writeString( suggestion.getTooltip().getString(), 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 83340b96c9..4515e1078e 100644 --- a/proxy/src/main/java/net/md_5/bungee/BungeeCord.java +++ b/proxy/src/main/java/net/md_5/bungee/BungeeCord.java @@ -315,6 +315,12 @@ public void startListeners() if ( info.isProxyProtocol() ) { getLogger().log( Level.WARNING, "Using PROXY protocol for listener {0}, please ensure this listener is adequately firewalled.", info.getHost() ); + + if ( connectionThrottle != null ) + { + connectionThrottle = null; + getLogger().log( Level.WARNING, "Since PROXY protocol is in use, internal connection throttle has been disabled." ); + } } ChannelFutureListener listener = new ChannelFutureListener() diff --git a/proxy/src/main/java/net/md_5/bungee/BungeeCordLauncher.java b/proxy/src/main/java/net/md_5/bungee/BungeeCordLauncher.java index fdfb6222b8..9bad64e9d2 100644 --- a/proxy/src/main/java/net/md_5/bungee/BungeeCordLauncher.java +++ b/proxy/src/main/java/net/md_5/bungee/BungeeCordLauncher.java @@ -28,15 +28,21 @@ 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( "noconsole" ) ); + parser.acceptsAll( Arrays.asList( "help" ), "Show the help" ); + parser.acceptsAll( Arrays.asList( "v", "version" ), "Print version and exit" ); + parser.acceptsAll( Arrays.asList( "noconsole" ), "Disable console input" ); OptionSet options = parser.parse( args ); - if ( options.has("version") ) + if ( options.has( "help" ) ) + { + parser.printHelpOn( System.out ); + return; + } + if ( options.has( "version" ) ) { System.out.println( BungeeCord.class.getPackage().getImplementationVersion() ); return; @@ -45,7 +51,7 @@ public static void main(String[] args) throws Exception if ( BungeeCord.class.getPackage().getSpecificationVersion() != null && System.getProperty( "IReallyKnowWhatIAmDoingISwear" ) == null) { String version = BungeeCord.class.getPackage().getSpecificationVersion(); - + if ( version.equalsIgnoreCase("unknown") ) { System.err.println( "*** You are using a self compiled version ***" ); @@ -56,7 +62,7 @@ public static void main(String[] args) throws Exception } else { int currentVersion = Integer.parseInt( version ); - + try { URL api = new URL( "https://api.github.com/repos/HexagonMC/BungeeCord/releases/latest" ); @@ -64,16 +70,16 @@ public static void main(String[] args) throws Exception // 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 ***"); diff --git a/proxy/src/main/java/net/md_5/bungee/BungeeServerInfo.java b/proxy/src/main/java/net/md_5/bungee/BungeeServerInfo.java index c0703afaa4..3ff3446b5a 100644 --- a/proxy/src/main/java/net/md_5/bungee/BungeeServerInfo.java +++ b/proxy/src/main/java/net/md_5/bungee/BungeeServerInfo.java @@ -69,11 +69,17 @@ public Collection getPlayers() return Collections.unmodifiableCollection( new HashSet<>( players ) ); } + @Override + public String getPermission() + { + return "bungeecord.server." + name; + } + @Override public boolean canAccess(CommandSender player) { Preconditions.checkNotNull( player, "player" ); - return !restricted || player.hasPermission( "bungeecord.server." + name ); + return !restricted || player.hasPermission( getPermission() ); } @Override 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 0b5eceffeb..3d70a9bf72 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 @@ -63,7 +63,6 @@ public class Configuration implements ProxyConfig private boolean alwaysHandlePackets = false; private boolean preventProxyConnections; private boolean forgeSupport; - private boolean injectCommands; public void load() { @@ -97,11 +96,6 @@ public void load() alwaysHandlePackets = adapter.getBoolean( "always_handle_packets", false ); preventProxyConnections = adapter.getBoolean( "prevent_proxy_connections", preventProxyConnections ); forgeSupport = adapter.getBoolean( "forge_support", forgeSupport ); - injectCommands = adapter.getBoolean( "inject_commands", injectCommands ); - if ( injectCommands ) - { - System.setProperty( "net.md-5.bungee.protocol.register_commands", "true" ); - } disabledCommands = new CaseInsensitiveSet( (Collection) adapter.getList( "disabled_commands", Arrays.asList( "disabledcommandhere" ) ) ); 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 5bab8ae379..4374a7042b 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,18 +1,25 @@ package net.md_5.bungee.connection; +import com.google.common.base.Function; import com.google.common.base.Preconditions; +import com.google.common.collect.Lists; import com.google.common.io.ByteArrayDataOutput; import com.google.common.io.ByteStreams; import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.builder.LiteralArgumentBuilder; import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import com.mojang.brigadier.context.StringRange; +import com.mojang.brigadier.suggestion.Suggestion; import com.mojang.brigadier.suggestion.SuggestionProvider; +import com.mojang.brigadier.suggestion.Suggestions; import com.mojang.brigadier.tree.LiteralCommandNode; import java.io.DataInput; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; import io.netty.buffer.Unpooled; +import java.util.ArrayList; +import java.util.List; import java.util.Map; import lombok.RequiredArgsConstructor; import net.md_5.bungee.BungeeCord; @@ -60,11 +67,11 @@ @RequiredArgsConstructor public class DownstreamBridge extends PacketHandler { - + private final ProxyServer bungee; private final UserConnection con; private final ServerConnection server; - + @Override public void exception(Throwable t) throws Exception { @@ -83,7 +90,7 @@ public void exception(Throwable t) throws Exception con.disconnect( Util.exception( t ) ); } } - + @Override public void disconnected(ChannelWrapper channel) throws Exception { @@ -91,41 +98,41 @@ public void disconnected(ChannelWrapper channel) throws Exception 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.getPendingConnection().getVersion() ); 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)); throw CancelSendSignal.INSTANCE; // Always throw because of profile rewriting } - + @Override public void handle(ScoreboardObjective objective) throws Exception { @@ -152,7 +159,7 @@ public void handle(ScoreboardObjective objective) throws Exception throw new IllegalArgumentException("Unknown objective action: " + objective.getAction()); } } - + @Override public void handle(ScoreboardScore score) throws Exception { @@ -171,7 +178,7 @@ public void handle(ScoreboardScore score) throws Exception throw new IllegalArgumentException("Unknown scoreboard action: " + score.getAction()); } } - + @Override public void handle(ScoreboardDisplay displayScoreboard) throws Exception { @@ -179,7 +186,7 @@ public void handle(ScoreboardDisplay displayScoreboard) throws Exception serverScoreboard.setName(displayScoreboard.getName()); serverScoreboard.setPosition(Position.values()[displayScoreboard.getPosition()]); } - + @Override public void handle(net.md_5.bungee.protocol.packet.Team team) throws Exception { @@ -190,7 +197,7 @@ public void handle(net.md_5.bungee.protocol.packet.Team team) throws Exception serverScoreboard.removeTeam(team.getName()); return; } - + // Create or get old team Team t; if (team.getMode() == 0) @@ -200,7 +207,7 @@ public void handle(net.md_5.bungee.protocol.packet.Team team) throws Exception } else t = serverScoreboard.getTeam(team.getName()); - + if ( t != null ) { if ( team.getMode() == 0 || team.getMode() == 2 ) @@ -228,7 +235,7 @@ public void handle(net.md_5.bungee.protocol.packet.Team team) throws Exception } } } - + @Override public void handle(PluginMessage pluginMessage) throws Exception { @@ -267,12 +274,12 @@ public void handle(PluginMessage pluginMessage) throws Exception con.unsafe().sendPacket(pluginMessage); throw CancelSendSignal.INSTANCE; } - + if (pluginMessage.getTag().equals("BungeeCord")) { ByteArrayDataOutput out = ByteStreams.newDataOutput(); String subChannel = in.readUTF(); - + if (subChannel.equals("ForwardToPlayer")) { ProxiedPlayer target = bungee.getPlayer(in.readUTF()); @@ -283,16 +290,16 @@ public void handle(PluginMessage pluginMessage) throws Exception short len = in.readShort(); byte[] data = new byte[len]; in.readFully(data); - + // Prepare new data to send out.writeUTF(channel); out.writeShort(data.length); out.write(data); byte[] payload = out.toByteArray(); - + target.getServer().sendData("BungeeCord", payload); } - + // Null out stream, important as we don't want to send to ourselves out = null; } @@ -304,16 +311,16 @@ public void handle(PluginMessage pluginMessage) throws Exception short len = in.readShort(); byte[] data = new byte[len]; in.readFully(data); - + // Prepare new data to send 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")) { for ( ServerInfo server : bungee.getServers().values() ) @@ -465,7 +472,7 @@ public void handle(PluginMessage pluginMessage) throws Exception 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) { @@ -475,11 +482,11 @@ public void handle(PluginMessage pluginMessage) throws Exception server.sendData( "BungeeCord", b ); } } - + throw CancelSendSignal.INSTANCE; } } - + @Override public void handle(Kick kick) throws Exception { @@ -495,32 +502,60 @@ 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()); } - + @Override public void handle(TabCompleteResponse tabCompleteResponse) throws Exception { - if ( tabCompleteResponse.getCommands() == null ) + List commands = tabCompleteResponse.getCommands(); + if ( commands == null ) { - // Passthrough on 1.13 style command responses - unclear of a sane way to process them at the moment, contributions welcome - return; + commands = Lists.transform( tabCompleteResponse.getSuggestions().getList(), new Function() + { + @Override + public String apply(Suggestion input) + { + return input.getText(); + } + } ); } - TabCompleteResponseEvent tabCompleteResponseEvent = new TabCompleteResponseEvent( server, con, tabCompleteResponse.getCommands() ); - + TabCompleteResponseEvent tabCompleteResponseEvent = new TabCompleteResponseEvent( server, con, new ArrayList<>( commands ) ); if ( !bungee.getPluginManager().callEvent( tabCompleteResponseEvent ).isCancelled() ) { + // Take action only if modified + if ( !commands.equals( tabCompleteResponseEvent.getSuggestions() ) ) + { + if ( tabCompleteResponse.getCommands() != null ) + { + // Classic style + tabCompleteResponse.setCommands( tabCompleteResponseEvent.getSuggestions() ); + } else + { + // Brigadier style + final StringRange range = tabCompleteResponse.getSuggestions().getRange(); + tabCompleteResponse.setSuggestions( new Suggestions( range, Lists.transform( tabCompleteResponseEvent.getSuggestions(), new Function() + { + @Override + public Suggestion apply(String input) + { + return new Suggestion( range, input ); + } + } ) ) ); + } + } + con.unsafe().sendPacket( tabCompleteResponse ); } throw CancelSendSignal.INSTANCE; } - + @Override public void handle(BossBar bossBar) { @@ -536,7 +571,7 @@ public void handle(BossBar bossBar) break; } } - + @Override public void handle(Respawn respawn) { @@ -548,20 +583,17 @@ public void handle(Commands commands) throws Exception { boolean modified = false; - if ( BungeeCord.getInstance().config.isInjectCommands() ) + for ( Map.Entry command : bungee.getPluginManager().getCommands() ) { - for ( Map.Entry command : bungee.getPluginManager().getCommands() ) + if ( !bungee.getDisabledCommands().contains( command.getKey() ) && commands.getRoot().getChild( command.getKey() ) == null && command.getValue().hasPermission( con ) ) { - if ( commands.getRoot().getChild( command.getKey() ) == null && command.getValue().hasPermission( con ) ) - { - LiteralCommandNode dummy = LiteralArgumentBuilder.literal( command.getKey() ) - .then( RequiredArgumentBuilder.argument( "args", StringArgumentType.greedyString() ) - .suggests( Commands.SuggestionRegistry.ASK_SERVER ) ) - .build(); - commands.getRoot().addChild( dummy ); + LiteralCommandNode dummy = LiteralArgumentBuilder.literal( command.getKey() ) + .then( RequiredArgumentBuilder.argument( "args", StringArgumentType.greedyString() ) + .suggests( Commands.SuggestionRegistry.ASK_SERVER ) ) + .build(); + commands.getRoot().addChild( dummy ); - modified = true; - } + modified = true; } } 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 ffdb1f6b32..893c5fc6fb 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 @@ -179,7 +179,7 @@ public void handle(TabCompleteRequest tabComplete) throws Exception if ( con.getPendingConnection().getVersion() < ProtocolConstants.MINECRAFT_1_13 ) { con.unsafe().sendPacket( new TabCompleteResponse( results ) ); - } else if ( BungeeCord.getInstance().config.isInjectCommands() ) + } else { int start = tabComplete.getCursor().lastIndexOf( ' ' ) + 1; int end = tabComplete.getCursor().length(); 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 d3822d5694..80e0fb9f1f 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 @@ -246,7 +246,7 @@ protected static void rewriteMetaVarInt(ByteBuf packet, int oldId, int newId, in private static void readSkipSlot(ByteBuf packet, int protocolVersion) { - if ( (protocolVersion >= ProtocolConstants.MINECRAFT_1_13_2) ? packet.readBoolean() : packet.readShort() != -1 ) + if ( ( protocolVersion >= ProtocolConstants.MINECRAFT_1_13_2 ) ? packet.readBoolean() : packet.readShort() != -1 ) { if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_13_2 ) { diff --git a/proxy/src/main/java/net/md_5/bungee/util/ChatComponentTransformer.java b/proxy/src/main/java/net/md_5/bungee/util/ChatComponentTransformer.java index ad26893e2b..d69c35d90d 100644 --- a/proxy/src/main/java/net/md_5/bungee/util/ChatComponentTransformer.java +++ b/proxy/src/main/java/net/md_5/bungee/util/ChatComponentTransformer.java @@ -51,7 +51,7 @@ public static ChatComponentTransformer getInstance() */ public BaseComponent[] transform(ProxiedPlayer player, BaseComponent... component) { - if ( component == null || component.length < 1 || ( component.length == 1 && component[0] == null ) ) + if ( component == null || component.length < 1 || ( component.length == 1 && component[0] == null ) ) { return new BaseComponent[] { 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 4ac87e7d88..b89811234b 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 @@ -50,6 +50,17 @@ private void writeString(ByteBuf buf, String s) @Override protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket msg) throws Exception + { + try + { + handleMessage( ctx, msg ); + } catch ( Throwable t ) + { + bungee.getLogger().log( Level.WARNING, "Error whilst handling query packet from " + msg.sender(), t ); + } + } + + private void handleMessage(ChannelHandlerContext ctx, DatagramPacket msg) { ByteBuf in = msg.content(); if ( in.readUnsignedByte() != 0xFE || in.readUnsignedByte() != 0xFD )