diff --git a/README.md b/README.md index 0eb0a2d7ea..77404c7004 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ -BungeeCord for 1.7/1.8/1.9/1.10/1.11/1.12/1.13/1.14/1.15/1.16 +BungeeCord for 1.7/1.8/1.9/1.10/1.11/1.12/1.13/1.14/1.15/1.16/1.17 ========== **Fork:** [BungeeCord](https://github.com/SpigotMC/BungeeCord) >> [HexaCord](https://github.com/HexagonMC/BungeeCord) >> [KettleCord](https://github.com/UeberallGebannt/KettleCord/) diff --git a/api/pom.xml b/api/pom.xml index aff963d3d2..e64231f560 100644 --- a/api/pom.xml +++ b/api/pom.xml @@ -6,13 +6,13 @@ net.md-5 bungeecord-parent - 1.16-R0.5-SNAPSHOT + 1.17-R0.1-SNAPSHOT ../pom.xml net.md-5 bungeecord-api - 1.16-R0.5-SNAPSHOT + 1.17-R0.1-SNAPSHOT jar BungeeCord-API @@ -49,10 +49,31 @@ ${netty.version} compile + + org.apache.maven + maven-resolver-provider + 3.8.1 + + provided + + + org.apache.maven.resolver + maven-resolver-connector-basic + 1.7.0 + + provided + + + org.apache.maven.resolver + maven-resolver-transport-http + 1.7.0 + + provided + org.yaml snakeyaml - 1.26 + 1.28 compile 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 dadf089ba5..29a4716fec 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 @@ -57,8 +57,7 @@ public enum MainHand String getDisplayName(); /** - * Sets this players display name to be used as their nametag and tab list - * name. + * Sets this players display name to be used by bungeecord commands and plugins. * * @param name the name to set */ diff --git a/api/src/main/java/net/md_5/bungee/api/plugin/LibraryLoader.java b/api/src/main/java/net/md_5/bungee/api/plugin/LibraryLoader.java new file mode 100644 index 0000000000..55e166c8f0 --- /dev/null +++ b/api/src/main/java/net/md_5/bungee/api/plugin/LibraryLoader.java @@ -0,0 +1,123 @@ +package net.md_5.bungee.api.plugin; + +import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.apache.maven.repository.internal.MavenRepositorySystemUtils; +import org.eclipse.aether.DefaultRepositorySystemSession; +import org.eclipse.aether.RepositorySystem; +import org.eclipse.aether.artifact.Artifact; +import org.eclipse.aether.artifact.DefaultArtifact; +import org.eclipse.aether.collection.CollectRequest; +import org.eclipse.aether.connector.basic.BasicRepositoryConnectorFactory; +import org.eclipse.aether.graph.Dependency; +import org.eclipse.aether.impl.DefaultServiceLocator; +import org.eclipse.aether.repository.LocalRepository; +import org.eclipse.aether.repository.RemoteRepository; +import org.eclipse.aether.repository.RepositoryPolicy; +import org.eclipse.aether.resolution.ArtifactResult; +import org.eclipse.aether.resolution.DependencyRequest; +import org.eclipse.aether.resolution.DependencyResolutionException; +import org.eclipse.aether.resolution.DependencyResult; +import org.eclipse.aether.spi.connector.RepositoryConnectorFactory; +import org.eclipse.aether.spi.connector.transport.TransporterFactory; +import org.eclipse.aether.transfer.AbstractTransferListener; +import org.eclipse.aether.transfer.TransferCancelledException; +import org.eclipse.aether.transfer.TransferEvent; +import org.eclipse.aether.transport.http.HttpTransporterFactory; + +class LibraryLoader +{ + + private final Logger logger; + private final RepositorySystem repository; + private final DefaultRepositorySystemSession session; + private final List repositories; + + public LibraryLoader(Logger logger) + { + this.logger = logger; + + DefaultServiceLocator locator = MavenRepositorySystemUtils.newServiceLocator(); + locator.addService( RepositoryConnectorFactory.class, BasicRepositoryConnectorFactory.class ); + locator.addService( TransporterFactory.class, HttpTransporterFactory.class ); + + this.repository = locator.getService( RepositorySystem.class ); + this.session = MavenRepositorySystemUtils.newSession(); + + session.setChecksumPolicy( RepositoryPolicy.CHECKSUM_POLICY_FAIL ); + session.setLocalRepositoryManager( repository.newLocalRepositoryManager( session, new LocalRepository( "libraries" ) ) ); + session.setTransferListener( new AbstractTransferListener() + { + @Override + public void transferStarted(TransferEvent event) throws TransferCancelledException + { + logger.log( Level.INFO, "Downloading {0}", event.getResource().getRepositoryUrl() + event.getResource().getResourceName() ); + } + } ); + session.setReadOnly(); + + this.repositories = repository.newResolutionRepositories( session, Arrays.asList( new RemoteRepository.Builder( "central", "default", "https://repo.maven.apache.org/maven2" ).build() ) ); + } + + public ClassLoader createLoader(PluginDescription desc) + { + if ( desc.getLibraries().isEmpty() ) + { + return null; + } + logger.log( Level.INFO, "[{0}] Loading {1} libraries... please wait", new Object[] + { + desc.getName(), desc.getLibraries().size() + } ); + + List dependencies = new ArrayList<>(); + for ( String library : desc.getLibraries() ) + { + Artifact artifact = new DefaultArtifact( library ); + Dependency dependency = new Dependency( artifact, null ); + + dependencies.add( dependency ); + } + + DependencyResult result; + try + { + result = repository.resolveDependencies( session, new DependencyRequest( new CollectRequest( (Dependency) null, dependencies, repositories ), null ) ); + } catch ( DependencyResolutionException ex ) + { + throw new RuntimeException( "Error resolving libraries", ex ); + } + + List jarFiles = new ArrayList<>(); + for ( ArtifactResult artifact : result.getArtifactResults() ) + { + File file = artifact.getArtifact().getFile(); + + URL url; + try + { + url = file.toURI().toURL(); + } catch ( MalformedURLException ex ) + { + throw new AssertionError( ex ); + } + + jarFiles.add( url ); + logger.log( Level.INFO, "[{0}] Loaded library {1}", new Object[] + { + desc.getName(), file + } ); + } + + URLClassLoader loader = new URLClassLoader( jarFiles.toArray( new URL[ 0 ] ) ); + + return loader; + } +} diff --git a/api/src/main/java/net/md_5/bungee/api/plugin/PluginClassloader.java b/api/src/main/java/net/md_5/bungee/api/plugin/PluginClassloader.java index 75c75e2db1..75cf6e3339 100644 --- a/api/src/main/java/net/md_5/bungee/api/plugin/PluginClassloader.java +++ b/api/src/main/java/net/md_5/bungee/api/plugin/PluginClassloader.java @@ -1,12 +1,23 @@ package net.md_5.bungee.api.plugin; import com.google.common.base.Preconditions; +import com.google.common.io.ByteStreams; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; import java.net.URL; import java.net.URLClassLoader; +import java.security.CodeSigner; +import java.security.CodeSource; import java.util.Set; import java.util.concurrent.CopyOnWriteArraySet; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; +import java.util.jar.Manifest; +import lombok.ToString; import net.md_5.bungee.api.ProxyServer; +@ToString(of = "desc") final class PluginClassloader extends URLClassLoader { @@ -14,6 +25,10 @@ final class PluginClassloader extends URLClassLoader // private final ProxyServer proxy; private final PluginDescription desc; + private final JarFile jar; + private final Manifest manifest; + private final URL url; + private final ClassLoader libraryLoader; // private Plugin plugin; @@ -22,11 +37,18 @@ final class PluginClassloader extends URLClassLoader ClassLoader.registerAsParallelCapable(); } - public PluginClassloader(ProxyServer proxy, PluginDescription desc, URL[] urls) + public PluginClassloader(ProxyServer proxy, PluginDescription desc, File file, ClassLoader libraryLoader) throws IOException { - super( urls ); + super( new URL[] + { + file.toURI().toURL() + } ); this.proxy = proxy; this.desc = desc; + this.jar = new JarFile( file ); + this.manifest = jar.getManifest(); + this.url = file.toURI().toURL(); + this.libraryLoader = libraryLoader; allLoaders.add( this ); } @@ -34,10 +56,10 @@ public PluginClassloader(ProxyServer proxy, PluginDescription desc, URL[] urls) @Override protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { - return loadClass0( name, resolve, true ); + return loadClass0( name, resolve, true, true ); } - private Class loadClass0(String name, boolean resolve, boolean checkOther) throws ClassNotFoundException + private Class loadClass0(String name, boolean resolve, boolean checkOther, boolean checkLibraries) throws ClassNotFoundException { try { @@ -45,6 +67,17 @@ private Class loadClass0(String name, boolean resolve, boolean checkOther) th } catch ( ClassNotFoundException ex ) { } + + if ( checkLibraries && libraryLoader != null ) + { + try + { + return libraryLoader.loadClass( name ); + } catch ( ClassNotFoundException ex ) + { + } + } + if ( checkOther ) { for ( PluginClassloader loader : allLoaders ) @@ -53,16 +86,81 @@ private Class loadClass0(String name, boolean resolve, boolean checkOther) th { try { - return loader.loadClass0( name, resolve, false ); + return loader.loadClass0( name, resolve, false, proxy.getPluginManager().isTransitiveDepend( desc, loader.desc ) ); } catch ( ClassNotFoundException ex ) { } } } } + throw new ClassNotFoundException( name ); } + @Override + protected Class findClass(String name) throws ClassNotFoundException + { + String path = name.replace( '.', '/' ).concat( ".class" ); + JarEntry entry = jar.getJarEntry( path ); + + if ( entry != null ) + { + byte[] classBytes; + + try ( InputStream is = jar.getInputStream( entry ) ) + { + classBytes = ByteStreams.toByteArray( is ); + } catch ( IOException ex ) + { + throw new ClassNotFoundException( name, ex ); + } + + int dot = name.lastIndexOf( '.' ); + if ( dot != -1 ) + { + String pkgName = name.substring( 0, dot ); + if ( getPackage( pkgName ) == null ) + { + try + { + if ( manifest != null ) + { + definePackage( pkgName, manifest, url ); + } else + { + definePackage( pkgName, null, null, null, null, null, null, null ); + } + } catch ( IllegalArgumentException ex ) + { + if ( getPackage( pkgName ) == null ) + { + throw new IllegalStateException( "Cannot find package " + pkgName ); + } + } + } + } + + CodeSigner[] signers = entry.getCodeSigners(); + CodeSource source = new CodeSource( url, signers ); + + return defineClass( name, classBytes, 0, classBytes.length, source ); + } + + return super.findClass( name ); + } + + @Override + public void close() throws IOException + { + try + { + super.close(); + } finally + { + jar.close(); + } + } + void init(Plugin plugin) { Preconditions.checkArgument( plugin != null, "plugin" ); diff --git a/api/src/main/java/net/md_5/bungee/api/plugin/PluginDescription.java b/api/src/main/java/net/md_5/bungee/api/plugin/PluginDescription.java index ef12ae9037..ea5c0d375e 100644 --- a/api/src/main/java/net/md_5/bungee/api/plugin/PluginDescription.java +++ b/api/src/main/java/net/md_5/bungee/api/plugin/PluginDescription.java @@ -2,6 +2,8 @@ import java.io.File; import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; import java.util.Set; import lombok.AllArgsConstructor; import lombok.Data; @@ -48,4 +50,8 @@ public class PluginDescription * Optional description. */ private String description = null; + /** + * Optional libraries. + */ + private List libraries = new LinkedList<>(); } 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 b4da08dcd6..c122cad97d 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 @@ -4,10 +4,12 @@ import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Multimap; import com.google.common.eventbus.Subscribe; +import com.google.common.graph.GraphBuilder; +import com.google.common.graph.Graphs; +import com.google.common.graph.MutableGraph; import java.io.File; import java.io.InputStream; import java.lang.reflect.Method; -import java.net.URL; import java.net.URLClassLoader; import java.util.Arrays; import java.util.Collection; @@ -49,6 +51,8 @@ public final class PluginManager private final Yaml yaml; private final EventBus eventBus; private final Map plugins = new LinkedHashMap<>(); + private final MutableGraph dependencyGraph = GraphBuilder.directed().build(); + private final LibraryLoader libraryLoader; private final Map commandMap = new HashMap<>(); private Map toLoad = new HashMap<>(); private final Multimap commandsByPlugin = ArrayListMultimap.create(); @@ -67,6 +71,17 @@ public PluginManager(ProxyServer proxy) yaml = new Yaml( yamlConstructor ); eventBus = new EventBus( proxy.getLogger() ); + + LibraryLoader libraryLoader = null; + try + { + libraryLoader = new LibraryLoader( proxy.getLogger() ); + } catch ( NoClassDefFoundError ex ) + { + // Provided depends were not added back + proxy.getLogger().warning( "Could not initialize LibraryLoader (missing dependencies?)" ); + } + this.libraryLoader = libraryLoader; } /** @@ -309,6 +324,7 @@ private boolean enablePlugin(Map pluginStatuses, Sta status = false; } + dependencyGraph.putEdge( plugin.getName(), dependName ); if ( !status ) { break; @@ -320,10 +336,7 @@ private boolean enablePlugin(Map pluginStatuses, Sta { try { - URLClassLoader loader = new PluginClassloader( proxy, plugin, new URL[] - { - plugin.getFile().toURI().toURL() - } ); + URLClassLoader loader = new PluginClassloader( proxy, plugin, plugin.getFile(), ( libraryLoader != null ) ? libraryLoader.createLoader( plugin ) : null ); Class main = loader.loadClass( plugin.getMain() ); Plugin clazz = (Plugin) main.getDeclaredConstructor().newInstance(); @@ -335,7 +348,7 @@ private boolean enablePlugin(Map pluginStatuses, Sta } ); } catch ( Throwable t ) { - proxy.getLogger().log( Level.WARNING, "Error enabling plugin " + plugin.getName(), t ); + proxy.getLogger().log( Level.WARNING, "Error loading plugin " + plugin.getName(), t ); } } @@ -463,4 +476,19 @@ public Collection> getCommands() { return Collections.unmodifiableCollection( commandMap.entrySet() ); } + + boolean isTransitiveDepend(PluginDescription plugin, PluginDescription depend) + { + Preconditions.checkArgument( plugin != null, "plugin" ); + Preconditions.checkArgument( depend != null, "depend" ); + + if ( dependencyGraph.nodes().contains( plugin.getName() ) ) + { + if ( Graphs.reachableNodes( dependencyGraph, plugin.getName() ).contains( depend.getName() ) ) + { + return true; + } + } + return false; + } } diff --git a/bootstrap/pom.xml b/bootstrap/pom.xml index 092b6a76b8..a35a8318be 100644 --- a/bootstrap/pom.xml +++ b/bootstrap/pom.xml @@ -6,13 +6,13 @@ net.md-5 bungeecord-parent - 1.16-R0.5-SNAPSHOT + 1.17-R0.1-SNAPSHOT ../pom.xml net.md-5 bungeecord-bootstrap - 1.16-R0.5-SNAPSHOT + 1.17-R0.1-SNAPSHOT jar BungeeCord-Bootstrap @@ -79,4 +79,25 @@ + + + + jdk-9-release + + [9,) + + + 6 + + + + jdk-12-release + + [12,) + + + 7 + + + diff --git a/chat/pom.xml b/chat/pom.xml index d7aca2adc2..fb797b1eb6 100644 --- a/chat/pom.xml +++ b/chat/pom.xml @@ -6,13 +6,13 @@ net.md-5 bungeecord-parent - 1.16-R0.5-SNAPSHOT + 1.17-R0.1-SNAPSHOT ../pom.xml net.md-5 bungeecord-chat - 1.16-R0.5-SNAPSHOT + 1.17-R0.1-SNAPSHOT jar BungeeCord-Chat diff --git a/chat/src/main/java/net/md_5/bungee/api/ChatColor.java b/chat/src/main/java/net/md_5/bungee/api/ChatColor.java index 272d217e77..d7747deb33 100644 --- a/chat/src/main/java/net/md_5/bungee/api/ChatColor.java +++ b/chat/src/main/java/net/md_5/bungee/api/ChatColor.java @@ -300,7 +300,7 @@ public static ChatColor valueOf(String name) @Deprecated public static ChatColor[] values() { - return BY_CHAR.values().toArray( new ChatColor[ BY_CHAR.values().size() ] ); + return BY_CHAR.values().toArray( new ChatColor[ 0 ] ); } /** diff --git a/chat/src/main/java/net/md_5/bungee/api/chat/ComponentBuilder.java b/chat/src/main/java/net/md_5/bungee/api/chat/ComponentBuilder.java index 1f8dd4c8e1..a7e505371b 100644 --- a/chat/src/main/java/net/md_5/bungee/api/chat/ComponentBuilder.java +++ b/chat/src/main/java/net/md_5/bungee/api/chat/ComponentBuilder.java @@ -57,7 +57,7 @@ private ComponentBuilder(BaseComponent[] parts) */ public ComponentBuilder(ComponentBuilder original) { - this( original.parts.toArray( new BaseComponent[ original.parts.size() ] ) ); + this( original.parts.toArray( new BaseComponent[ 0 ] ) ); } /** diff --git a/chat/src/main/java/net/md_5/bungee/api/chat/TextComponent.java b/chat/src/main/java/net/md_5/bungee/api/chat/TextComponent.java index a7b9af73e1..1598dcc562 100644 --- a/chat/src/main/java/net/md_5/bungee/api/chat/TextComponent.java +++ b/chat/src/main/java/net/md_5/bungee/api/chat/TextComponent.java @@ -157,7 +157,7 @@ public static BaseComponent[] fromLegacyText(String message, ChatColor defaultCo component.setText( builder.toString() ); components.add( component ); - return components.toArray( new BaseComponent[ components.size() ] ); + return components.toArray( new BaseComponent[ 0 ] ); } /** diff --git a/config/pom.xml b/config/pom.xml index 298a80ef0b..88c71b99c5 100644 --- a/config/pom.xml +++ b/config/pom.xml @@ -6,13 +6,13 @@ net.md-5 bungeecord-parent - 1.16-R0.5-SNAPSHOT + 1.17-R0.1-SNAPSHOT ../pom.xml net.md-5 bungeecord-config - 1.16-R0.5-SNAPSHOT + 1.17-R0.1-SNAPSHOT jar BungeeCord-Config @@ -29,7 +29,7 @@ org.yaml snakeyaml - 1.26 + 1.28 compile true diff --git a/event/pom.xml b/event/pom.xml index 6c26e547b4..3a9c76345b 100644 --- a/event/pom.xml +++ b/event/pom.xml @@ -6,13 +6,13 @@ net.md-5 bungeecord-parent - 1.16-R0.5-SNAPSHOT + 1.17-R0.1-SNAPSHOT ../pom.xml net.md-5 bungeecord-event - 1.16-R0.5-SNAPSHOT + 1.17-R0.1-SNAPSHOT jar BungeeCord-Event diff --git a/event/src/main/java/net/md_5/bungee/event/EventBus.java b/event/src/main/java/net/md_5/bungee/event/EventBus.java index f5bd1f9801..a6d717f2cd 100644 --- a/event/src/main/java/net/md_5/bungee/event/EventBus.java +++ b/event/src/main/java/net/md_5/bungee/event/EventBus.java @@ -1,5 +1,6 @@ package net.md_5.bungee.event; +import com.google.common.collect.ImmutableSet; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.text.MessageFormat; @@ -61,7 +62,8 @@ public void post(Object event) private Map, Map>> findHandlers(Object listener) { Map, Map>> handler = new HashMap<>(); - for ( Method m : listener.getClass().getDeclaredMethods() ) + Set methods = ImmutableSet.builder().add( listener.getClass().getMethods() ).add( listener.getClass().getDeclaredMethods() ).build(); + for ( final Method m : methods ) { EventHandler annotation = m.getAnnotation( EventHandler.class ); if ( annotation != null ) @@ -115,8 +117,7 @@ public void register(Object listener) currentPriorityMap = new HashMap<>(); prioritiesMap.put( entry.getKey(), currentPriorityMap ); } - Method[] baked = new Method[ entry.getValue().size() ]; - currentPriorityMap.put( listener, entry.getValue().toArray( baked ) ); + currentPriorityMap.put( listener, entry.getValue().toArray( new Method[ 0 ] ) ); } bakeHandlers( e.getKey() ); } @@ -194,7 +195,7 @@ private void bakeHandlers(Class eventClass) } } } while ( value++ < Byte.MAX_VALUE ); - byEventBaked.put( eventClass, handlersList.toArray( new EventHandlerMethod[ handlersList.size() ] ) ); + byEventBaked.put( eventClass, handlersList.toArray( new EventHandlerMethod[ 0 ] ) ); } else { byEventBaked.remove( eventClass ); diff --git a/event/src/test/java/net/md_5/bungee/event/SubclassTest.java b/event/src/test/java/net/md_5/bungee/event/SubclassTest.java new file mode 100644 index 0000000000..be4b380451 --- /dev/null +++ b/event/src/test/java/net/md_5/bungee/event/SubclassTest.java @@ -0,0 +1,26 @@ +package net.md_5.bungee.event; + +import java.util.concurrent.CountDownLatch; +import org.junit.Assert; +import org.junit.Test; + +public class SubclassTest extends EventBusTest +{ + + private final CountDownLatch latch = new CountDownLatch( 1 ); + + @Test + @Override + public void testNestedEvents() + { + super.testNestedEvents(); + Assert.assertEquals( 0, latch.getCount() ); + } + + @EventHandler + protected void extraListener(FirstEvent event) + { + Assert.assertEquals( 1, latch.getCount() ); + latch.countDown(); + } +} diff --git a/log/pom.xml b/log/pom.xml index fd735eb7b3..6d6242e1d7 100644 --- a/log/pom.xml +++ b/log/pom.xml @@ -6,13 +6,13 @@ net.md-5 bungeecord-parent - 1.16-R0.5-SNAPSHOT + 1.17-R0.1-SNAPSHOT ../pom.xml net.md-5 bungeecord-log - 1.16-R0.5-SNAPSHOT + 1.17-R0.1-SNAPSHOT jar BungeeCord-Log diff --git a/log/src/main/java/net/md_5/bungee/log/BungeeLogger.java b/log/src/main/java/net/md_5/bungee/log/BungeeLogger.java index c2062bf849..68481e8200 100644 --- a/log/src/main/java/net/md_5/bungee/log/BungeeLogger.java +++ b/log/src/main/java/net/md_5/bungee/log/BungeeLogger.java @@ -26,6 +26,7 @@ public BungeeLogger(String loggerName, String filePattern, ConsoleReader reader) try { FileHandler fileHandler = new FileHandler( filePattern, 1 << 24, 8, true ); + fileHandler.setLevel( Level.parse( System.getProperty( "net.md_5.bungee.file-log-level", "INFO" ) ) ); fileHandler.setFormatter( new ConciseFormatter( false ) ); addHandler( fileHandler ); diff --git a/module/cmd-alert/pom.xml b/module/cmd-alert/pom.xml index 7d912e9026..4b3a82ea9c 100644 --- a/module/cmd-alert/pom.xml +++ b/module/cmd-alert/pom.xml @@ -6,13 +6,13 @@ net.md-5 bungeecord-module - 1.16-R0.5-SNAPSHOT + 1.17-R0.1-SNAPSHOT ../pom.xml net.md-5 bungeecord-module-cmd-alert - 1.16-R0.5-SNAPSHOT + 1.17-R0.1-SNAPSHOT jar cmd_alert diff --git a/module/cmd-find/pom.xml b/module/cmd-find/pom.xml index c8f2353fa0..1c7f2515c4 100644 --- a/module/cmd-find/pom.xml +++ b/module/cmd-find/pom.xml @@ -6,13 +6,13 @@ net.md-5 bungeecord-module - 1.16-R0.5-SNAPSHOT + 1.17-R0.1-SNAPSHOT ../pom.xml net.md-5 bungeecord-module-cmd-find - 1.16-R0.5-SNAPSHOT + 1.17-R0.1-SNAPSHOT jar cmd_find diff --git a/module/cmd-list/pom.xml b/module/cmd-list/pom.xml index 46dd4b651e..91fadc2b96 100644 --- a/module/cmd-list/pom.xml +++ b/module/cmd-list/pom.xml @@ -6,13 +6,13 @@ net.md-5 bungeecord-module - 1.16-R0.5-SNAPSHOT + 1.17-R0.1-SNAPSHOT ../pom.xml net.md-5 bungeecord-module-cmd-list - 1.16-R0.5-SNAPSHOT + 1.17-R0.1-SNAPSHOT jar cmd_list diff --git a/module/cmd-send/pom.xml b/module/cmd-send/pom.xml index 6158b2cbe5..30097fc3ca 100644 --- a/module/cmd-send/pom.xml +++ b/module/cmd-send/pom.xml @@ -6,13 +6,13 @@ net.md-5 bungeecord-module - 1.16-R0.5-SNAPSHOT + 1.17-R0.1-SNAPSHOT ../pom.xml net.md-5 bungeecord-module-cmd-send - 1.16-R0.5-SNAPSHOT + 1.17-R0.1-SNAPSHOT jar cmd_send diff --git a/module/cmd-server/pom.xml b/module/cmd-server/pom.xml index 7ce143ad7c..d69f1e612e 100644 --- a/module/cmd-server/pom.xml +++ b/module/cmd-server/pom.xml @@ -6,13 +6,13 @@ net.md-5 bungeecord-module - 1.16-R0.5-SNAPSHOT + 1.17-R0.1-SNAPSHOT ../pom.xml net.md-5 bungeecord-module-cmd-server - 1.16-R0.5-SNAPSHOT + 1.17-R0.1-SNAPSHOT jar cmd_server diff --git a/module/pom.xml b/module/pom.xml index e0cec205af..dbc316dd05 100644 --- a/module/pom.xml +++ b/module/pom.xml @@ -6,13 +6,13 @@ net.md-5 bungeecord-parent - 1.16-R0.5-SNAPSHOT + 1.17-R0.1-SNAPSHOT ../pom.xml net.md-5 bungeecord-module - 1.16-R0.5-SNAPSHOT + 1.17-R0.1-SNAPSHOT pom BungeeCord Modules diff --git a/module/reconnect-yaml/pom.xml b/module/reconnect-yaml/pom.xml index 5d3d81d5e2..8d1df1fd91 100644 --- a/module/reconnect-yaml/pom.xml +++ b/module/reconnect-yaml/pom.xml @@ -6,13 +6,13 @@ net.md-5 bungeecord-module - 1.16-R0.5-SNAPSHOT + 1.17-R0.1-SNAPSHOT ../pom.xml net.md-5 bungeecord-module-reconnect-yaml - 1.16-R0.5-SNAPSHOT + 1.17-R0.1-SNAPSHOT jar reconnect_yaml diff --git a/native/pom.xml b/native/pom.xml index cf46174c05..f8bacabd63 100644 --- a/native/pom.xml +++ b/native/pom.xml @@ -6,13 +6,13 @@ net.md-5 bungeecord-parent - 1.16-R0.5-SNAPSHOT + 1.17-R0.1-SNAPSHOT ../pom.xml net.md-5 bungeecord-native - 1.16-R0.5-SNAPSHOT + 1.17-R0.1-SNAPSHOT jar BungeeCord-Native diff --git a/pom.xml b/pom.xml index eec8328479..757e4bbee5 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ net.md-5 bungeecord-parent - 1.16-R0.5-SNAPSHOT + 1.17-R0.1-SNAPSHOT pom BungeeCord-Parent @@ -47,6 +47,7 @@ protocol proxy query + slf4j native @@ -77,7 +78,8 @@ unknown - 4.1.53.Final + 1.18.20 + 4.1.65.Final 1.8 1.8 UTF-8 @@ -105,7 +107,7 @@ org.projectlombok lombok - 1.18.10 + ${lombok.version} provided @@ -152,6 +154,53 @@ + + jdk-9-release + + [9,) + + + 8 + + + + jdk-9-javadoc + + [9,) + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + -html5 + + + + + + + + jdk-15-javadoc + + [15,) + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + none + + + + + + dist @@ -172,7 +221,7 @@ org.projectlombok lombok-maven-plugin - 1.18.10.0 + 1.18.20.0 package @@ -186,6 +235,13 @@ ${project.build.directory}/delombok ${project.build.sourceDirectory} + + + org.projectlombok + lombok + ${lombok.version} + + org.apache.maven.plugins diff --git a/protocol/pom.xml b/protocol/pom.xml index 5ec853a571..f66ca6ca9d 100644 --- a/protocol/pom.xml +++ b/protocol/pom.xml @@ -6,13 +6,13 @@ net.md-5 bungeecord-parent - 1.16-R0.5-SNAPSHOT + 1.17-R0.1-SNAPSHOT ../pom.xml net.md-5 bungeecord-protocol - 1.16-R0.5-SNAPSHOT + 1.17-R0.1-SNAPSHOT jar BungeeCord-Protocol diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/AbstractPacketHandler.java b/protocol/src/main/java/net/md_5/bungee/protocol/AbstractPacketHandler.java index ac31e435e0..15a61b7efe 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/AbstractPacketHandler.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/AbstractPacketHandler.java @@ -2,6 +2,7 @@ import net.md_5.bungee.protocol.packet.BossBar; import net.md_5.bungee.protocol.packet.Chat; +import net.md_5.bungee.protocol.packet.ClearTitles; import net.md_5.bungee.protocol.packet.ClientSettings; import net.md_5.bungee.protocol.packet.ClientStatus; import net.md_5.bungee.protocol.packet.Commands; @@ -30,10 +31,12 @@ import net.md_5.bungee.protocol.packet.SetCompression; import net.md_5.bungee.protocol.packet.StatusRequest; import net.md_5.bungee.protocol.packet.StatusResponse; +import net.md_5.bungee.protocol.packet.Subtitle; import net.md_5.bungee.protocol.packet.TabCompleteRequest; import net.md_5.bungee.protocol.packet.TabCompleteResponse; import net.md_5.bungee.protocol.packet.Team; import net.md_5.bungee.protocol.packet.Title; +import net.md_5.bungee.protocol.packet.TitleTimes; import net.md_5.bungee.protocol.packet.ViewDistance; public abstract class AbstractPacketHandler @@ -127,6 +130,18 @@ public void handle(Title title) throws Exception { } + public void handle(Subtitle title) throws Exception + { + } + + public void handle(TitleTimes title) throws Exception + { + } + + public void handle(ClearTitles title) throws Exception + { + } + public void handle(PluginMessage pluginMessage) throws Exception { } 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 a0297a3986..dd210d3ed8 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 @@ -32,17 +32,28 @@ public static void writeString(String s, ByteBuf buf) } public static String readString(ByteBuf buf) + { + return readString( buf, Short.MAX_VALUE ); + } + + public static String readString(ByteBuf buf, int maxLen) { int len = readVarInt( buf ); - if ( len > Short.MAX_VALUE ) + if ( len > maxLen * 4 ) { - throw new OverflowPacketException( String.format( "Cannot receive string longer than Short.MAX_VALUE (got %s characters)", len ) ); + throw new OverflowPacketException( String.format( "Cannot receive string longer than %d (got %d bytes)", maxLen * 4, len ) ); } byte[] b = new byte[ len ]; buf.readBytes( b ); - return new String( b, Charsets.UTF_8 ); + String s = new String( b, Charsets.UTF_8 ); + if ( s.length() > maxLen ) + { + throw new OverflowPacketException( String.format( "Cannot receive string longer than %d (got %d characters)", maxLen, s.length() ) ); + } + + return s; } public static void writeArray(byte[] b, ByteBuf buf) 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 829f90e7c1..d1deada338 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 @@ -6,11 +6,12 @@ import gnu.trove.map.TObjectIntMap; import gnu.trove.map.hash.TIntObjectHashMap; import gnu.trove.map.hash.TObjectIntHashMap; -import java.lang.reflect.Constructor; +import java.util.function.Supplier; import lombok.Data; import lombok.Getter; import net.md_5.bungee.protocol.packet.BossBar; import net.md_5.bungee.protocol.packet.Chat; +import net.md_5.bungee.protocol.packet.ClearTitles; import net.md_5.bungee.protocol.packet.ClientSettings; import net.md_5.bungee.protocol.packet.Commands; import net.md_5.bungee.protocol.packet.EncryptionRequest; @@ -36,10 +37,12 @@ import net.md_5.bungee.protocol.packet.SetCompression; import net.md_5.bungee.protocol.packet.StatusRequest; import net.md_5.bungee.protocol.packet.StatusResponse; +import net.md_5.bungee.protocol.packet.Subtitle; import net.md_5.bungee.protocol.packet.TabCompleteRequest; import net.md_5.bungee.protocol.packet.TabCompleteResponse; import net.md_5.bungee.protocol.packet.Team; import net.md_5.bungee.protocol.packet.Title; +import net.md_5.bungee.protocol.packet.TitleTimes; import net.md_5.bungee.protocol.packet.ViewDistance; public enum Protocol @@ -52,6 +55,7 @@ public enum Protocol { TO_SERVER.registerPacket( Handshake.class, + Handshake::new, map( ProtocolConstants.MINECRAFT_1_7_2, 0x00 ) ); } @@ -63,33 +67,40 @@ public enum Protocol { TO_CLIENT.registerPacket( KeepAlive.class, + KeepAlive::new, map( ProtocolConstants.MINECRAFT_1_7_2, 0x00 ), map( ProtocolConstants.MINECRAFT_1_9, 0x1F ), map( ProtocolConstants.MINECRAFT_1_13, 0x21 ), map( ProtocolConstants.MINECRAFT_1_14, 0x20 ), map( ProtocolConstants.MINECRAFT_1_15, 0x21 ), map( ProtocolConstants.MINECRAFT_1_16, 0x20 ), - map( ProtocolConstants.MINECRAFT_1_16_2, 0x1F ) + map( ProtocolConstants.MINECRAFT_1_16_2, 0x1F ), + map( ProtocolConstants.MINECRAFT_1_17, 0x21 ) ); TO_CLIENT.registerPacket( Login.class, + Login::new, map( ProtocolConstants.MINECRAFT_1_7_2, 0x01 ), map( ProtocolConstants.MINECRAFT_1_9, 0x23 ), map( ProtocolConstants.MINECRAFT_1_13, 0x25 ), map( ProtocolConstants.MINECRAFT_1_15, 0x26 ), map( ProtocolConstants.MINECRAFT_1_16, 0x25 ), - map( ProtocolConstants.MINECRAFT_1_16_2, 0x24 ) + map( ProtocolConstants.MINECRAFT_1_16_2, 0x24 ), + map( ProtocolConstants.MINECRAFT_1_17, 0x26 ) ); TO_CLIENT.registerPacket( Chat.class, + Chat::new, map( ProtocolConstants.MINECRAFT_1_7_2, 0x02 ), map( ProtocolConstants.MINECRAFT_1_9, 0x0F ), map( ProtocolConstants.MINECRAFT_1_13, 0x0E ), map( ProtocolConstants.MINECRAFT_1_15, 0x0F ), - map( ProtocolConstants.MINECRAFT_1_16, 0x0E ) + map( ProtocolConstants.MINECRAFT_1_16, 0x0E ), + map( ProtocolConstants.MINECRAFT_1_17, 0x0F ) ); TO_CLIENT.registerPacket( Respawn.class, + Respawn::new, map( ProtocolConstants.MINECRAFT_1_7_2, 0x07 ), map( ProtocolConstants.MINECRAFT_1_9, 0x33 ), map( ProtocolConstants.MINECRAFT_1_12, 0x34 ), @@ -98,16 +109,20 @@ public enum Protocol map( ProtocolConstants.MINECRAFT_1_14, 0x3A ), map( ProtocolConstants.MINECRAFT_1_15, 0x3B ), map( ProtocolConstants.MINECRAFT_1_16, 0x3A ), - map( ProtocolConstants.MINECRAFT_1_16_2, 0x39 ) + map( ProtocolConstants.MINECRAFT_1_16_2, 0x39 ), + map( ProtocolConstants.MINECRAFT_1_17, 0x3D ) ); TO_CLIENT.registerPacket( BossBar.class, + BossBar::new, map( ProtocolConstants.MINECRAFT_1_9, 0x0C ), map( ProtocolConstants.MINECRAFT_1_15, 0x0D ), - map( ProtocolConstants.MINECRAFT_1_16, 0x0C ) + map( ProtocolConstants.MINECRAFT_1_16, 0x0C ), + map( ProtocolConstants.MINECRAFT_1_17, 0x0D ) ); TO_CLIENT.registerPacket( PlayerListItem.class, // PlayerInfo + PlayerListItem::new, map( ProtocolConstants.MINECRAFT_1_7_2, 0x38 ), map( ProtocolConstants.MINECRAFT_1_9, 0x2D ), map( ProtocolConstants.MINECRAFT_1_12_1, 0x2E ), @@ -115,89 +130,122 @@ public enum Protocol map( ProtocolConstants.MINECRAFT_1_14, 0x33 ), map( ProtocolConstants.MINECRAFT_1_15, 0x34 ), map( ProtocolConstants.MINECRAFT_1_16, 0x33 ), - map( ProtocolConstants.MINECRAFT_1_16_2, 0x32 ) + map( ProtocolConstants.MINECRAFT_1_16_2, 0x32 ), + map( ProtocolConstants.MINECRAFT_1_17, 0x36 ) ); TO_CLIENT.registerPacket( TabCompleteResponse.class, + TabCompleteResponse::new, map( ProtocolConstants.MINECRAFT_1_7_2, 0x3A ), map( ProtocolConstants.MINECRAFT_1_9, 0x0E ), map( ProtocolConstants.MINECRAFT_1_13, 0x10 ), map( ProtocolConstants.MINECRAFT_1_15, 0x11 ), map( ProtocolConstants.MINECRAFT_1_16, 0x10 ), - map( ProtocolConstants.MINECRAFT_1_16_2, 0x0F ) + map( ProtocolConstants.MINECRAFT_1_16_2, 0x0F ), + map( ProtocolConstants.MINECRAFT_1_17, 0x11 ) ); TO_CLIENT.registerPacket( ScoreboardObjective.class, + ScoreboardObjective::new, 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 ), map( ProtocolConstants.MINECRAFT_1_13, 0x45 ), map( ProtocolConstants.MINECRAFT_1_14, 0x49 ), - map( ProtocolConstants.MINECRAFT_1_15, 0x4A ) + map( ProtocolConstants.MINECRAFT_1_15, 0x4A ), + map( ProtocolConstants.MINECRAFT_1_17, 0x53 ) ); TO_CLIENT.registerPacket( ScoreboardScore.class, + ScoreboardScore::new, 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 ), map( ProtocolConstants.MINECRAFT_1_13, 0x48 ), map( ProtocolConstants.MINECRAFT_1_14, 0x4C ), - map( ProtocolConstants.MINECRAFT_1_15, 0x4D ) + map( ProtocolConstants.MINECRAFT_1_15, 0x4D ), + map( ProtocolConstants.MINECRAFT_1_17, 0x56 ) ); TO_CLIENT.registerPacket( ScoreboardDisplay.class, + ScoreboardDisplay::new, 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 ), map( ProtocolConstants.MINECRAFT_1_13, 0x3E ), map( ProtocolConstants.MINECRAFT_1_14, 0x42 ), - map( ProtocolConstants.MINECRAFT_1_15, 0x43 ) + map( ProtocolConstants.MINECRAFT_1_15, 0x43 ), + map( ProtocolConstants.MINECRAFT_1_17, 0x4C ) ); TO_CLIENT.registerPacket( Team.class, + Team::new, 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 ), map( ProtocolConstants.MINECRAFT_1_13, 0x47 ), map( ProtocolConstants.MINECRAFT_1_14, 0x4B ), - map( ProtocolConstants.MINECRAFT_1_15, 0x4C ) + map( ProtocolConstants.MINECRAFT_1_15, 0x4C ), + map( ProtocolConstants.MINECRAFT_1_17, 0x55 ) ); TO_CLIENT.registerPacket( PluginMessage.class, + PluginMessage::new, map( ProtocolConstants.MINECRAFT_1_7_2, 0x3F ), map( ProtocolConstants.MINECRAFT_1_9, 0x18 ), map( ProtocolConstants.MINECRAFT_1_13, 0x19 ), map( ProtocolConstants.MINECRAFT_1_14, 0x18 ), map( ProtocolConstants.MINECRAFT_1_15, 0x19 ), map( ProtocolConstants.MINECRAFT_1_16, 0x18 ), - map( ProtocolConstants.MINECRAFT_1_16_2, 0x17 ) + map( ProtocolConstants.MINECRAFT_1_16_2, 0x17 ), + map( ProtocolConstants.MINECRAFT_1_17, 0x18 ) ); TO_CLIENT.registerPacket( Kick.class, + Kick::new, map( ProtocolConstants.MINECRAFT_1_7_2, 0x40 ), map( ProtocolConstants.MINECRAFT_1_9, 0x1A ), map( ProtocolConstants.MINECRAFT_1_13, 0x1B ), map( ProtocolConstants.MINECRAFT_1_14, 0x1A ), map( ProtocolConstants.MINECRAFT_1_15, 0x1B ), map( ProtocolConstants.MINECRAFT_1_16, 0x1A ), - map( ProtocolConstants.MINECRAFT_1_16_2, 0x19 ) + map( ProtocolConstants.MINECRAFT_1_16_2, 0x19 ), + map( ProtocolConstants.MINECRAFT_1_17, 0x1A ) ); TO_CLIENT.registerPacket( Title.class, + Title::new, map( ProtocolConstants.MINECRAFT_1_8, 0x45 ), map( ProtocolConstants.MINECRAFT_1_12, 0x47 ), map( ProtocolConstants.MINECRAFT_1_12_1, 0x48 ), map( ProtocolConstants.MINECRAFT_1_13, 0x4B ), map( ProtocolConstants.MINECRAFT_1_14, 0x4F ), map( ProtocolConstants.MINECRAFT_1_15, 0x50 ), - map( ProtocolConstants.MINECRAFT_1_16, 0x4F ) + map( ProtocolConstants.MINECRAFT_1_16, 0x4F ), + map( ProtocolConstants.MINECRAFT_1_17, 0x59 ) + ); + TO_CLIENT.registerPacket( + ClearTitles.class, + ClearTitles::new, + map( ProtocolConstants.MINECRAFT_1_17, 0x10 ) + ); + TO_CLIENT.registerPacket( + Subtitle.class, + Subtitle::new, + map( ProtocolConstants.MINECRAFT_1_17, 0x57 ) + ); + TO_CLIENT.registerPacket( + TitleTimes.class, + TitleTimes::new, + map( ProtocolConstants.MINECRAFT_1_17, 0x5A ) ); TO_CLIENT.registerPacket( PlayerListHeaderFooter.class, + PlayerListHeaderFooter::new, map( ProtocolConstants.MINECRAFT_1_8, 0x47 ), map( ProtocolConstants.MINECRAFT_1_9, 0x48 ), map( ProtocolConstants.MINECRAFT_1_9_4, 0x47 ), @@ -206,50 +254,62 @@ public enum Protocol map( ProtocolConstants.MINECRAFT_1_13, 0x4E ), map( ProtocolConstants.MINECRAFT_1_14, 0x53 ), map( ProtocolConstants.MINECRAFT_1_15, 0x54 ), - map( ProtocolConstants.MINECRAFT_1_16, 0x53 ) + map( ProtocolConstants.MINECRAFT_1_16, 0x53 ), + map( ProtocolConstants.MINECRAFT_1_17, 0x5E ) ); TO_CLIENT.registerPacket( EntityStatus.class, + EntityStatus::new, map( ProtocolConstants.MINECRAFT_1_7_2, 0x1A ), map( ProtocolConstants.MINECRAFT_1_9, 0x1B ), map( ProtocolConstants.MINECRAFT_1_13, 0x1C ), map( ProtocolConstants.MINECRAFT_1_14, 0x1B ), map( ProtocolConstants.MINECRAFT_1_15, 0x1C ), map( ProtocolConstants.MINECRAFT_1_16, 0x1B ), - map( ProtocolConstants.MINECRAFT_1_16_2, 0x1A ) + map( ProtocolConstants.MINECRAFT_1_16_2, 0x1A ), + map( ProtocolConstants.MINECRAFT_1_17, 0x1B ) ); TO_CLIENT.registerPacket( Commands.class, + Commands::new, map( ProtocolConstants.MINECRAFT_1_13, 0x11 ), map( ProtocolConstants.MINECRAFT_1_15, 0x12 ), map( ProtocolConstants.MINECRAFT_1_16, 0x11 ), - map( ProtocolConstants.MINECRAFT_1_16_2, 0x10 ) + map( ProtocolConstants.MINECRAFT_1_16_2, 0x10 ), + map( ProtocolConstants.MINECRAFT_1_17, 0x12 ) ); TO_CLIENT.registerPacket( GameState.class, + GameState::new, map( ProtocolConstants.MINECRAFT_1_15, 0x1F ), map( ProtocolConstants.MINECRAFT_1_16, 0x1E ), - map( ProtocolConstants.MINECRAFT_1_16_2, 0x1D ) + map( ProtocolConstants.MINECRAFT_1_16_2, 0x1D ), + map( ProtocolConstants.MINECRAFT_1_17, 0x1E ) ); TO_CLIENT.registerPacket( ViewDistance.class, + ViewDistance::new, map( ProtocolConstants.MINECRAFT_1_14, 0x41 ), map( ProtocolConstants.MINECRAFT_1_15, 0x42 ), - map( ProtocolConstants.MINECRAFT_1_16, 0x41 ) + map( ProtocolConstants.MINECRAFT_1_16, 0x41 ), + map( ProtocolConstants.MINECRAFT_1_17, 0x4A ) ); TO_SERVER.registerPacket( KeepAlive.class, + KeepAlive::new, 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 ), map( ProtocolConstants.MINECRAFT_1_13, 0x0E ), map( ProtocolConstants.MINECRAFT_1_14, 0x0F ), - map( ProtocolConstants.MINECRAFT_1_16, 0x10 ) + map( ProtocolConstants.MINECRAFT_1_16, 0x10 ), + map( ProtocolConstants.MINECRAFT_1_17, 0x0F ) ); TO_SERVER.registerPacket( Chat.class, + Chat::new, map( ProtocolConstants.MINECRAFT_1_7_2, 0x01 ), map( ProtocolConstants.MINECRAFT_1_9, 0x02 ), map( ProtocolConstants.MINECRAFT_1_12, 0x03 ), @@ -258,6 +318,7 @@ public enum Protocol ); TO_SERVER.registerPacket( TabCompleteRequest.class, + TabCompleteRequest::new, map( ProtocolConstants.MINECRAFT_1_7_2, 0x14 ), map( ProtocolConstants.MINECRAFT_1_9, 0x01 ), map( ProtocolConstants.MINECRAFT_1_12, 0x02 ), @@ -267,6 +328,7 @@ public enum Protocol ); TO_SERVER.registerPacket( ClientSettings.class, + ClientSettings::new, map( ProtocolConstants.MINECRAFT_1_7_2, 0x15 ), map( ProtocolConstants.MINECRAFT_1_9, 0x04 ), map( ProtocolConstants.MINECRAFT_1_12, 0x05 ), @@ -275,12 +337,14 @@ public enum Protocol ); TO_SERVER.registerPacket( PluginMessage.class, + PluginMessage::new, 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 ), map( ProtocolConstants.MINECRAFT_1_13, 0x0A ), - map( ProtocolConstants.MINECRAFT_1_14, 0x0B ) + map( ProtocolConstants.MINECRAFT_1_14, 0x0B ), + map( ProtocolConstants.MINECRAFT_1_17, 0x0A ) ); } }, @@ -291,19 +355,23 @@ public enum Protocol { TO_CLIENT.registerPacket( StatusResponse.class, + StatusResponse::new, map( ProtocolConstants.MINECRAFT_1_7_2, 0x00 ) ); TO_CLIENT.registerPacket( PingPacket.class, + PingPacket::new, map( ProtocolConstants.MINECRAFT_1_7_2, 0x01 ) ); TO_SERVER.registerPacket( StatusRequest.class, + StatusRequest::new, map( ProtocolConstants.MINECRAFT_1_7_2, 0x00 ) ); TO_SERVER.registerPacket( PingPacket.class, + PingPacket::new, map( ProtocolConstants.MINECRAFT_1_7_2, 0x01 ) ); } @@ -315,35 +383,43 @@ public enum Protocol { TO_CLIENT.registerPacket( Kick.class, + Kick::new, map( ProtocolConstants.MINECRAFT_1_7_2, 0x00 ) ); TO_CLIENT.registerPacket( EncryptionRequest.class, + EncryptionRequest::new, map( ProtocolConstants.MINECRAFT_1_7_2, 0x01 ) ); TO_CLIENT.registerPacket( LoginSuccess.class, + LoginSuccess::new, map( ProtocolConstants.MINECRAFT_1_7_2, 0x02 ) ); TO_CLIENT.registerPacket( SetCompression.class, + SetCompression::new, map( ProtocolConstants.MINECRAFT_1_8, 0x03 ) ); TO_CLIENT.registerPacket( LoginPayloadRequest.class, + LoginPayloadRequest::new, map( ProtocolConstants.MINECRAFT_1_13, 0x04 ) ); TO_SERVER.registerPacket( LoginRequest.class, + LoginRequest::new, map( ProtocolConstants.MINECRAFT_1_7_2, 0x00 ) ); TO_SERVER.registerPacket( EncryptionResponse.class, + EncryptionResponse::new, map( ProtocolConstants.MINECRAFT_1_7_2, 0x01 ) ); TO_SERVER.registerPacket( LoginPayloadResponse.class, + LoginPayloadResponse::new, map( ProtocolConstants.MINECRAFT_1_13, 0x02 ) ); } @@ -394,7 +470,8 @@ 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 ); + @SuppressWarnings("unchecked") + private final Supplier[] packetConstructors = new Supplier[ MAX_PACKET_ID ]; } @Data @@ -450,55 +527,41 @@ public final DefinedPacket createPacket(int id, int version) } if ( id > MAX_PACKET_ID ) { - throw new BadPacketException( "Packet with id " + id + " outside of range " ); + throw new BadPacketException( "Packet with id " + id + " outside of range" ); } - Constructor constructor = protocolData.packetConstructors.get( id ); - try - { - return ( constructor == null ) ? null : constructor.newInstance(); - } catch ( ReflectiveOperationException ex ) - { - throw new BadPacketException( "Could not construct packet with id " + id, ex ); - } + Supplier constructor = protocolData.packetConstructors[id]; + return ( constructor == null ) ? null : constructor.get(); } - private void registerPacket(Class packetClass, ProtocolMapping... mappings) + private void registerPacket(Class packetClass, Supplier constructor, ProtocolMapping... mappings) { - try + int mappingIndex = 0; + ProtocolMapping mapping = mappings[mappingIndex]; + for ( int protocol : ProtocolConstants.SUPPORTED_VERSION_IDS ) { - Constructor constructor = packetClass.getDeclaredConstructor(); + if ( protocol < mapping.protocolVersion ) + { + // This is a new packet, skip it till we reach the next protocol + continue; + } - int mappingIndex = 0; - ProtocolMapping mapping = mappings[mappingIndex]; - for ( int protocol : ProtocolConstants.SUPPORTED_VERSION_IDS ) + if ( mapping.protocolVersion < protocol && mappingIndex + 1 < mappings.length ) { - if ( protocol < mapping.protocolVersion ) + // Mapping is non current, but the next one may be ok + ProtocolMapping nextMapping = mappings[mappingIndex + 1]; + if ( nextMapping.protocolVersion == protocol ) { - // This is a new packet, skip it till we reach the next protocol - continue; - } + Preconditions.checkState( nextMapping.packetID != mapping.packetID, "Duplicate packet mapping (%s, %s)", mapping.protocolVersion, nextMapping.protocolVersion ); - if ( mapping.protocolVersion < protocol && mappingIndex + 1 < mappings.length ) - { - // Mapping is non current, but the next one may be ok - ProtocolMapping nextMapping = mappings[mappingIndex + 1]; - if ( nextMapping.protocolVersion == protocol ) - { - Preconditions.checkState( nextMapping.packetID != mapping.packetID, "Duplicate packet mapping (%s, %s)", mapping.protocolVersion, nextMapping.protocolVersion ); - - mapping = nextMapping; - mappingIndex++; - } + mapping = nextMapping; + mappingIndex++; } - - ProtocolData data = protocols.get( protocol ); - data.packetMap.put( packetClass, mapping.packetID ); - data.packetConstructors.put( mapping.packetID, constructor ); } - } catch ( NoSuchMethodException ex ) - { - throw new BadPacketException( "No NoArgsConstructor for packet class " + packetClass ); + + ProtocolData data = protocols.get( protocol ); + data.packetMap.put( packetClass, mapping.packetID ); + data.packetConstructors[mapping.packetID] = constructor; } } 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 70794371b4..8757ed1000 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/ProtocolConstants.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/ProtocolConstants.java @@ -1,10 +1,12 @@ package net.md_5.bungee.protocol; -import java.util.Arrays; +import com.google.common.collect.ImmutableList; import java.util.List; public class ProtocolConstants { + + private static final boolean SNAPSHOT_SUPPORT = Boolean.getBoolean( "net.md_5.bungee.protocol.snapshot" ); 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; @@ -34,49 +36,67 @@ public class ProtocolConstants public static final int MINECRAFT_1_16_2 = 751; public static final int MINECRAFT_1_16_3 = 753; public static final int MINECRAFT_1_16_4 = 754; - 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", - "1.13.x", - "1.14.x", - "1.15.x", - "1.16.x" - ); - 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, - ProtocolConstants.MINECRAFT_1_9_4, - ProtocolConstants.MINECRAFT_1_10, - ProtocolConstants.MINECRAFT_1_11, - ProtocolConstants.MINECRAFT_1_11_1, - ProtocolConstants.MINECRAFT_1_12, - ProtocolConstants.MINECRAFT_1_12_1, - ProtocolConstants.MINECRAFT_1_12_2, - ProtocolConstants.MINECRAFT_1_13, - ProtocolConstants.MINECRAFT_1_13_1, - ProtocolConstants.MINECRAFT_1_13_2, - ProtocolConstants.MINECRAFT_1_14, - ProtocolConstants.MINECRAFT_1_14_1, - ProtocolConstants.MINECRAFT_1_14_2, - ProtocolConstants.MINECRAFT_1_14_3, - ProtocolConstants.MINECRAFT_1_14_4, - ProtocolConstants.MINECRAFT_1_15, - ProtocolConstants.MINECRAFT_1_15_1, - ProtocolConstants.MINECRAFT_1_15_2, - ProtocolConstants.MINECRAFT_1_16, - ProtocolConstants.MINECRAFT_1_16_1, - ProtocolConstants.MINECRAFT_1_16_2, - ProtocolConstants.MINECRAFT_1_16_3, - ProtocolConstants.MINECRAFT_1_16_4 - ); + public static final int MINECRAFT_1_17 = 755; + public static final List SUPPORTED_VERSIONS; + public static final List SUPPORTED_VERSION_IDS; + + static + { + ImmutableList.Builder supportedVersions = ImmutableList.builder().add( + "1.7.x", + "1.8.x", + "1.9.x", + "1.10.x", + "1.11.x", + "1.12.x", + "1.13.x", + "1.14.x", + "1.15.x", + "1.16.x", + "1.17.x" + ); + ImmutableList.Builder supportedVersionIds = ImmutableList.builder().add( + 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, + ProtocolConstants.MINECRAFT_1_9_4, + ProtocolConstants.MINECRAFT_1_10, + ProtocolConstants.MINECRAFT_1_11, + ProtocolConstants.MINECRAFT_1_11_1, + ProtocolConstants.MINECRAFT_1_12, + ProtocolConstants.MINECRAFT_1_12_1, + ProtocolConstants.MINECRAFT_1_12_2, + ProtocolConstants.MINECRAFT_1_13, + ProtocolConstants.MINECRAFT_1_13_1, + ProtocolConstants.MINECRAFT_1_13_2, + ProtocolConstants.MINECRAFT_1_14, + ProtocolConstants.MINECRAFT_1_14_1, + ProtocolConstants.MINECRAFT_1_14_2, + ProtocolConstants.MINECRAFT_1_14_3, + ProtocolConstants.MINECRAFT_1_14_4, + ProtocolConstants.MINECRAFT_1_15, + ProtocolConstants.MINECRAFT_1_15_1, + ProtocolConstants.MINECRAFT_1_15_2, + ProtocolConstants.MINECRAFT_1_16, + ProtocolConstants.MINECRAFT_1_16_1, + ProtocolConstants.MINECRAFT_1_16_2, + ProtocolConstants.MINECRAFT_1_16_3, + ProtocolConstants.MINECRAFT_1_16_4, + ProtocolConstants.MINECRAFT_1_17 + ); + + if ( SNAPSHOT_SUPPORT ) + { + // supportedVersions.add( "1.17.x" ); + // supportedVersionIds.add( ProtocolConstants.MINECRAFT_1_17 ); + } + + SUPPORTED_VERSIONS = supportedVersions.build(); + SUPPORTED_VERSION_IDS = supportedVersionIds.build(); + } public enum Direction { 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 8c0423080d..8907bdb38a 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 @@ -40,7 +40,7 @@ public Chat(String message, byte position, UUID sender) @Override public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) { - message = readString( buf ); + message = readString( buf, ( direction == ProtocolConstants.Direction.TO_CLIENT ) ? 262144 : 256 ); if ( direction == ProtocolConstants.Direction.TO_CLIENT && protocolVersion >= ProtocolConstants.MINECRAFT_1_8 ) { position = buf.readByte(); diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/packet/ClearTitles.java b/protocol/src/main/java/net/md_5/bungee/protocol/packet/ClearTitles.java new file mode 100644 index 0000000000..c37c0285a1 --- /dev/null +++ b/protocol/src/main/java/net/md_5/bungee/protocol/packet/ClearTitles.java @@ -0,0 +1,38 @@ +package net.md_5.bungee.protocol.packet; + +import io.netty.buffer.ByteBuf; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import net.md_5.bungee.protocol.AbstractPacketHandler; +import net.md_5.bungee.protocol.DefinedPacket; +import net.md_5.bungee.protocol.ProtocolConstants; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = false) +public class ClearTitles extends DefinedPacket +{ + + private boolean reset; + + @Override + public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) + { + reset = buf.readBoolean(); + } + + @Override + public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) + { + buf.writeBoolean( reset ); + } + + @Override + public void handle(AbstractPacketHandler handler) throws Exception + { + handler.handle( this ); + } +} 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 4639242c68..bc491b363d 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 @@ -23,11 +23,12 @@ public class ClientSettings extends DefinedPacket private byte difficulty; private byte skinParts; private int mainHand; + private boolean disableTextFiltering; @Override public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) { - locale = readString( buf ); + locale = readString( buf, 16 ); viewDistance = buf.readByte(); chatFlags = protocolVersion >= ProtocolConstants.MINECRAFT_1_9 ? DefinedPacket.readVarInt( buf ) : buf.readUnsignedByte(); chatColours = buf.readBoolean(); @@ -40,6 +41,10 @@ public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protoco { mainHand = DefinedPacket.readVarInt( buf ); } + if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_17 ) + { + disableTextFiltering = buf.readBoolean(); + } } @Override @@ -64,6 +69,10 @@ public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protoc { DefinedPacket.writeVarInt( mainHand, buf ); } + if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_17 ) + { + buf.writeBoolean( disableTextFiltering ); + } } @Override diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/packet/Handshake.java b/protocol/src/main/java/net/md_5/bungee/protocol/packet/Handshake.java index 70934a5bc6..7dbbfd3cd0 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/packet/Handshake.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/packet/Handshake.java @@ -24,7 +24,7 @@ public class Handshake extends DefinedPacket public void read(ByteBuf buf) { protocolVersion = readVarInt( buf ); - host = readString( buf ); + host = readString( buf, 255 ); port = buf.readUnsignedShort(); requestedProtocol = readVarInt( buf ); } diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/packet/Login.java b/protocol/src/main/java/net/md_5/bungee/protocol/packet/Login.java index c518eed7a1..a240ccbbff 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/packet/Login.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/packet/Login.java @@ -1,6 +1,5 @@ package net.md_5.bungee.protocol.packet; -import com.google.common.base.Preconditions; import io.netty.buffer.ByteBuf; import java.util.HashSet; import java.util.Set; @@ -53,8 +52,6 @@ public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protoco worldNames = new HashSet<>(); int worldCount = readVarInt( buf ); - Preconditions.checkArgument( worldCount < 128, "Too many worlds %s", worldCount ); - for ( int i = 0; i < worldCount; i++ ) { worldNames.add( readString( buf ) ); diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/packet/LoginRequest.java b/protocol/src/main/java/net/md_5/bungee/protocol/packet/LoginRequest.java index 32ba098cc6..08ee376e55 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/packet/LoginRequest.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/packet/LoginRequest.java @@ -1,7 +1,3 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ package net.md_5.bungee.protocol.packet; import io.netty.buffer.ByteBuf; @@ -24,7 +20,7 @@ public class LoginRequest extends DefinedPacket @Override public void read(ByteBuf buf) { - data = readString( buf ); + data = readString( buf, 16 ); } @Override diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/packet/Subtitle.java b/protocol/src/main/java/net/md_5/bungee/protocol/packet/Subtitle.java new file mode 100644 index 0000000000..6c842f0316 --- /dev/null +++ b/protocol/src/main/java/net/md_5/bungee/protocol/packet/Subtitle.java @@ -0,0 +1,36 @@ +package net.md_5.bungee.protocol.packet; + +import io.netty.buffer.ByteBuf; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import net.md_5.bungee.protocol.AbstractPacketHandler; +import net.md_5.bungee.protocol.DefinedPacket; +import net.md_5.bungee.protocol.ProtocolConstants; + +@Data +@NoArgsConstructor +@EqualsAndHashCode(callSuper = false) +public class Subtitle extends DefinedPacket +{ + + private String text; + + @Override + public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) + { + text = readString( buf ); + } + + @Override + public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) + { + writeString( text, buf ); + } + + @Override + public void handle(AbstractPacketHandler handler) throws Exception + { + handler.handle( this ); + } +} 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 7257d297c1..9927cb37a0 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 @@ -41,8 +41,7 @@ public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protoco { transactionId = readVarInt( buf ); } - - cursor = readString( buf ); + cursor = readString( buf, 32500 ); if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_8 && protocolVersion < ProtocolConstants.MINECRAFT_1_13 ) { @@ -50,6 +49,7 @@ public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protoco { assumeCommand = buf.readBoolean(); } + if ( hasPositon = buf.readBoolean() ) { position = buf.readLong(); @@ -64,7 +64,6 @@ public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protoc { writeVarInt( transactionId, buf ); } - writeString( cursor, buf ); if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_8 && protocolVersion < ProtocolConstants.MINECRAFT_1_13 ) diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/packet/Title.java b/protocol/src/main/java/net/md_5/bungee/protocol/packet/Title.java index 6bc1469cd5..331ac5c9f1 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/packet/Title.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/packet/Title.java @@ -24,9 +24,20 @@ public class Title extends DefinedPacket private int stay; private int fadeOut; + public Title(Action action) + { + this.action = action; + } + @Override public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) { + if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_17 ) + { + text = readString( buf ); + return; + } + int index = readVarInt( buf ); // If we're working on 1.10 or lower, increment the value of the index so we pull out the correct value. @@ -54,6 +65,12 @@ public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protoco @Override public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) { + if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_17 ) + { + writeString( text, buf ); + return; + } + int index = action.ordinal(); // If we're working on 1.10 or lower, increment the value of the index so we pull out the correct value. diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/packet/TitleTimes.java b/protocol/src/main/java/net/md_5/bungee/protocol/packet/TitleTimes.java new file mode 100644 index 0000000000..4252c00f1b --- /dev/null +++ b/protocol/src/main/java/net/md_5/bungee/protocol/packet/TitleTimes.java @@ -0,0 +1,42 @@ +package net.md_5.bungee.protocol.packet; + +import io.netty.buffer.ByteBuf; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import net.md_5.bungee.protocol.AbstractPacketHandler; +import net.md_5.bungee.protocol.DefinedPacket; +import net.md_5.bungee.protocol.ProtocolConstants; + +@Data +@NoArgsConstructor +@EqualsAndHashCode(callSuper = false) +public class TitleTimes extends DefinedPacket +{ + + private int fadeIn; + private int stay; + private int fadeOut; + + @Override + public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) + { + fadeIn = buf.readInt(); + stay = buf.readInt(); + fadeOut = buf.readInt(); + } + + @Override + public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) + { + buf.writeInt( fadeIn ); + buf.writeInt( stay ); + buf.writeInt( fadeOut ); + } + + @Override + public void handle(AbstractPacketHandler handler) throws Exception + { + handler.handle( this ); + } +} diff --git a/proxy/pom.xml b/proxy/pom.xml index d2cdf733d2..0f0af3dc2f 100644 --- a/proxy/pom.xml +++ b/proxy/pom.xml @@ -6,13 +6,13 @@ net.md-5 bungeecord-parent - 1.16-R0.5-SNAPSHOT + 1.17-R0.1-SNAPSHOT ../pom.xml net.md-5 bungeecord-proxy - 1.16-R0.5-SNAPSHOT + 1.17-R0.1-SNAPSHOT jar BungeeCord-Proxy @@ -79,6 +79,12 @@ ${project.version} compile + + net.md-5 + bungeecord-slf4j + ${project.version} + compile + net.sf.jopt-simple jopt-simple @@ -88,7 +94,26 @@ mysql mysql-connector-java - 5.1.48 + 5.1.49 + runtime + + + + org.apache.maven + maven-resolver-provider + 3.8.1 + runtime + + + org.apache.maven.resolver + maven-resolver-connector-basic + 1.7.0 + runtime + + + org.apache.maven.resolver + maven-resolver-transport-http + 1.7.0 runtime 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 69fa1c7907..3f8cbbd14f 100644 --- a/proxy/src/main/java/net/md_5/bungee/BungeeCord.java +++ b/proxy/src/main/java/net/md_5/bungee/BungeeCord.java @@ -96,6 +96,7 @@ import net.md_5.bungee.scheduler.BungeeScheduler; import net.md_5.bungee.util.CaseInsensitiveMap; import org.fusesource.jansi.AnsiConsole; +import org.slf4j.impl.JDK14LoggerFactory; /** * Main BungeeCord proxy class. @@ -226,6 +227,7 @@ public BungeeCord() throws IOException consoleReader.addCompleter( new ConsoleCommandCompleter( this ) ); logger = new BungeeLogger( "BungeeCord", "proxy.log", consoleReader ); + JDK14LoggerFactory.LOGGER = logger; System.setErr( new PrintStream( new LoggingOutputStream( logger, Level.SEVERE ), true ) ); System.setOut( new PrintStream( new LoggingOutputStream( logger, Level.INFO ), true ) ); 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 a30099f35b..89a4187f6c 100644 --- a/proxy/src/main/java/net/md_5/bungee/BungeeCordLauncher.java +++ b/proxy/src/main/java/net/md_5/bungee/BungeeCordLauncher.java @@ -27,6 +27,11 @@ public static void main(String[] args) throws Exception { Security.setProperty( "networkaddress.cache.ttl", "30" ); Security.setProperty( "networkaddress.cache.negative.ttl", "10" ); + // For JDK9+ we force-enable multi-release jar file support #3087 + if ( System.getProperty( "jdk.util.jar.enableMultiRelease" ) == null ) + { + System.setProperty( "jdk.util.jar.enableMultiRelease", "force" ); + } OptionParser parser = new OptionParser(); parser.allowsUnrecognizedOptions(); 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 e9073c5d4c..a6b76d9da4 100644 --- a/proxy/src/main/java/net/md_5/bungee/BungeeTitle.java +++ b/proxy/src/main/java/net/md_5/bungee/BungeeTitle.java @@ -1,30 +1,46 @@ package net.md_5.bungee; +import lombok.Data; import net.md_5.bungee.api.Title; import net.md_5.bungee.api.chat.BaseComponent; import net.md_5.bungee.api.connection.ProxiedPlayer; import net.md_5.bungee.chat.ComponentSerializer; import net.md_5.bungee.protocol.DefinedPacket; import net.md_5.bungee.protocol.ProtocolConstants; +import net.md_5.bungee.protocol.packet.ClearTitles; +import net.md_5.bungee.protocol.packet.Subtitle; import net.md_5.bungee.protocol.packet.Title.Action; +import net.md_5.bungee.protocol.packet.TitleTimes; public class BungeeTitle implements Title { - private net.md_5.bungee.protocol.packet.Title title, subtitle, times, clear, reset; + private TitlePacketHolder title; + private TitlePacketHolder subtitle; + private TitlePacketHolder times; + private TitlePacketHolder clear; + private TitlePacketHolder reset; - private static net.md_5.bungee.protocol.packet.Title createPacket(Action action) + @Data + private static class TitlePacketHolder { - net.md_5.bungee.protocol.packet.Title title = new net.md_5.bungee.protocol.packet.Title(); - title.setAction( action ); - if ( action == Action.TIMES ) - { - // Set packet to default values first - title.setFadeIn( 20 ); - title.setStay( 60 ); - title.setFadeOut( 20 ); - } + private final net.md_5.bungee.protocol.packet.Title oldPacket; + private final T newPacket; + } + + private static TitlePacketHolder createAnimationPacket() + { + TitlePacketHolder title = new TitlePacketHolder<>( new net.md_5.bungee.protocol.packet.Title( Action.TIMES ), new TitleTimes() ); + + title.oldPacket.setFadeIn( 20 ); + title.oldPacket.setStay( 60 ); + title.oldPacket.setFadeOut( 20 ); + + title.newPacket.setFadeIn( 20 ); + title.newPacket.setStay( 60 ); + title.newPacket.setFadeOut( 20 ); + return title; } @@ -33,10 +49,11 @@ public Title title(BaseComponent text) { if ( title == null ) { - title = createPacket( Action.TITLE ); + net.md_5.bungee.protocol.packet.Title packet = new net.md_5.bungee.protocol.packet.Title( Action.TITLE ); + title = new TitlePacketHolder<>( packet, packet ); } - title.setText( ComponentSerializer.toString( text ) ); + title.oldPacket.setText( ComponentSerializer.toString( text ) ); // = newPacket return this; } @@ -45,10 +62,11 @@ public Title title(BaseComponent... text) { if ( title == null ) { - title = createPacket( Action.TITLE ); + net.md_5.bungee.protocol.packet.Title packet = new net.md_5.bungee.protocol.packet.Title( Action.TITLE ); + title = new TitlePacketHolder<>( packet, packet ); } - title.setText( ComponentSerializer.toString( text ) ); + title.oldPacket.setText( ComponentSerializer.toString( text ) ); // = newPacket return this; } @@ -57,10 +75,12 @@ public Title subTitle(BaseComponent text) { if ( subtitle == null ) { - subtitle = createPacket( Action.SUBTITLE ); + subtitle = new TitlePacketHolder<>( new net.md_5.bungee.protocol.packet.Title( Action.SUBTITLE ), new Subtitle() ); } - subtitle.setText( ComponentSerializer.toString( text ) ); + String serialized = ComponentSerializer.toString( text ); + subtitle.oldPacket.setText( serialized ); + subtitle.newPacket.setText( serialized ); return this; } @@ -69,10 +89,12 @@ public Title subTitle(BaseComponent... text) { if ( subtitle == null ) { - subtitle = createPacket( Action.SUBTITLE ); + subtitle = new TitlePacketHolder<>( new net.md_5.bungee.protocol.packet.Title( Action.SUBTITLE ), new Subtitle() ); } - subtitle.setText( ComponentSerializer.toString( text ) ); + String serialized = ComponentSerializer.toString( text ); + subtitle.oldPacket.setText( serialized ); + subtitle.newPacket.setText( serialized ); return this; } @@ -81,10 +103,11 @@ public Title fadeIn(int ticks) { if ( times == null ) { - times = createPacket( Action.TIMES ); + times = createAnimationPacket(); } - times.setFadeIn( ticks ); + times.oldPacket.setFadeIn( ticks ); + times.newPacket.setFadeIn( ticks ); return this; } @@ -93,10 +116,11 @@ public Title stay(int ticks) { if ( times == null ) { - times = createPacket( Action.TIMES ); + times = createAnimationPacket(); } - times.setStay( ticks ); + times.oldPacket.setStay( ticks ); + times.newPacket.setStay( ticks ); return this; } @@ -105,10 +129,11 @@ public Title fadeOut(int ticks) { if ( times == null ) { - times = createPacket( Action.TIMES ); + times = createAnimationPacket(); } - times.setFadeOut( ticks ); + times.oldPacket.setFadeOut( ticks ); + times.newPacket.setFadeOut( ticks ); return this; } @@ -117,7 +142,7 @@ public Title clear() { if ( clear == null ) { - clear = createPacket( Action.CLEAR ); + clear = new TitlePacketHolder<>( new net.md_5.bungee.protocol.packet.Title( Action.CLEAR ), new ClearTitles() ); } title = null; // No need to send title if we clear it after that again @@ -130,7 +155,7 @@ public Title reset() { if ( reset == null ) { - reset = createPacket( Action.RESET ); + reset = new TitlePacketHolder<>( new net.md_5.bungee.protocol.packet.Title( Action.RESET ), new ClearTitles( true ) ); } // No need to send these packets if we reset them later @@ -141,11 +166,17 @@ public Title reset() return this; } - private static void sendPacket(ProxiedPlayer player, DefinedPacket packet) + private static void sendPacket(ProxiedPlayer player, TitlePacketHolder packet) { if ( packet != null ) { - player.unsafe().sendPacket( packet ); + if ( player.getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_17 ) + { + player.unsafe().sendPacket( packet.newPacket ); + } else + { + player.unsafe().sendPacket( packet.oldPacket ); + } } } 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 98f8d548a6..f89d3e3866 100644 --- a/proxy/src/main/java/net/md_5/bungee/ServerConnector.java +++ b/proxy/src/main/java/net/md_5/bungee/ServerConnector.java @@ -43,6 +43,8 @@ import net.md_5.bungee.protocol.packet.Handshake; import net.md_5.bungee.protocol.packet.Kick; import net.md_5.bungee.protocol.packet.Login; +import net.md_5.bungee.protocol.packet.LoginPayloadRequest; +import net.md_5.bungee.protocol.packet.LoginPayloadResponse; import net.md_5.bungee.protocol.packet.LoginRequest; import net.md_5.bungee.protocol.packet.LoginSuccess; import net.md_5.bungee.protocol.packet.PluginMessage; @@ -51,6 +53,7 @@ import net.md_5.bungee.protocol.packet.ScoreboardScore; import net.md_5.bungee.protocol.packet.SetCompression; import net.md_5.bungee.protocol.packet.ViewDistance; +import net.md_5.bungee.util.AddressUtil; import net.md_5.bungee.util.BufUtil; import net.md_5.bungee.util.QuietException; @@ -102,7 +105,7 @@ public void connected(ChannelWrapper channel) throws Exception if ( BungeeCord.getInstance().config.isIpForward() && user.getSocketAddress() instanceof InetSocketAddress ) { - String newHost = copiedHandshake.getHost() + "\00" + user.getAddress().getHostString() + "\00" + user.getUUID(); + String newHost = copiedHandshake.getHost() + "\00" + AddressUtil.sanitizeAddress( user.getAddress() ) + "\00" + user.getUUID(); // Handle properties. LoginResult.Property[] properties = new LoginResult.Property[0]; @@ -472,6 +475,12 @@ public void handle(PluginMessage pluginMessage) throws Exception user.unsafe().sendPacket( pluginMessage ); } + @Override + public void handle(LoginPayloadRequest loginPayloadRequest) + { + ch.write( new LoginPayloadResponse( loginPayloadRequest.getId(), null ) ); + } + @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 406def9e11..5a254eb3a9 100644 --- a/proxy/src/main/java/net/md_5/bungee/UserConnection.java +++ b/proxy/src/main/java/net/md_5/bungee/UserConnection.java @@ -148,7 +148,10 @@ public void sendPacket(DefinedPacket packet) public void init() { - this.entityRewrite = EntityMap.getEntityMap( getPendingConnection().getVersion() ); + if ( getPendingConnection().getVersion() < ProtocolConstants.MINECRAFT_1_16_2 || !bungee.getConfig().isIpForward() ) + { + this.entityRewrite = EntityMap.getEntityMap( getPendingConnection().getVersion() ); + } this.displayName = name; @@ -483,7 +486,7 @@ private void sendMessage(ChatMessageType position, UUID sender, BaseComponent... // transform score components message = ChatComponentTransformer.getInstance().transform( this, true, message ); - if ( position == ChatMessageType.ACTION_BAR && pendingConnection.getVersion() >= ProtocolConstants.MINECRAFT_1_8 ) + if ( position == ChatMessageType.ACTION_BAR && pendingConnection.getVersion() >= ProtocolConstants.MINECRAFT_1_8 && getPendingConnection().getVersion() < ProtocolConstants.MINECRAFT_1_17 ) { // Versions older than 1.11 cannot send the Action bar with the new JSON formattings // Fix by converting to a legacy message, see https://bugs.mojang.com/browse/MC-119145 diff --git a/proxy/src/main/java/net/md_5/bungee/compress/PacketDecompressor.java b/proxy/src/main/java/net/md_5/bungee/compress/PacketDecompressor.java index 21b3ea2bdb..445ee947ad 100644 --- a/proxy/src/main/java/net/md_5/bungee/compress/PacketDecompressor.java +++ b/proxy/src/main/java/net/md_5/bungee/compress/PacketDecompressor.java @@ -31,8 +31,7 @@ protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) t int size = DefinedPacket.readVarInt( in ); if ( size == 0 ) { - out.add( in.slice().retain() ); - in.skipBytes( in.readableBytes() ); + out.add( in.retain() ); } else { ByteBuf decompressed = ctx.alloc().directBuffer(); diff --git a/proxy/src/main/java/net/md_5/bungee/conf/YamlConfig.java b/proxy/src/main/java/net/md_5/bungee/conf/YamlConfig.java index c0620445c1..2691b8b84b 100644 --- a/proxy/src/main/java/net/md_5/bungee/conf/YamlConfig.java +++ b/proxy/src/main/java/net/md_5/bungee/conf/YamlConfig.java @@ -299,7 +299,10 @@ public Collection getListeners() @SuppressWarnings("unchecked") public Collection getGroups(String player) { - Collection groups = get( "groups." + player, null ); + // #1270: Do this to support player names with . + Map> raw = get( "groups", Collections.emptyMap() ); + Collection groups = raw.get( player ); + Collection ret = ( groups == null ) ? new HashSet() : new HashSet<>( groups ); ret.add( "default" ); return ret; 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 6c7b641f68..3cc4558eb1 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 @@ -354,7 +354,7 @@ public void handle(LoginRequest loginRequest) throws Exception Preconditions.checkState( thisState == State.USERNAME, "Not expecting USERNAME" ); this.loginRequest = loginRequest; - if ( getName().contains( "." ) ) + if ( getName().contains( " " ) ) { disconnect( bungee.getTranslation( "name_invalid" ) ); return; 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 9b62f0c06f..86a437dbdf 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 @@ -77,7 +77,9 @@ public static EntityMap getEntityMap(int version) case ProtocolConstants.MINECRAFT_1_16_2: case ProtocolConstants.MINECRAFT_1_16_3: case ProtocolConstants.MINECRAFT_1_16_4: - return EntityMap_1_16_2.INSTANCE; + return EntityMap_1_16_2.INSTANCE_1_16_2; + case ProtocolConstants.MINECRAFT_1_17: + return EntityMap_1_16_2.INSTANCE_1_17; } throw new RuntimeException( "Version " + version + " has no entity map" ); } diff --git a/proxy/src/main/java/net/md_5/bungee/entitymap/EntityMap_1_16_2.java b/proxy/src/main/java/net/md_5/bungee/entitymap/EntityMap_1_16_2.java index 88dd3f4358..df5516cacc 100644 --- a/proxy/src/main/java/net/md_5/bungee/entitymap/EntityMap_1_16_2.java +++ b/proxy/src/main/java/net/md_5/bungee/entitymap/EntityMap_1_16_2.java @@ -3,159 +3,46 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import io.netty.buffer.ByteBuf; import java.util.UUID; +import lombok.AccessLevel; +import lombok.RequiredArgsConstructor; import net.md_5.bungee.BungeeCord; import net.md_5.bungee.UserConnection; import net.md_5.bungee.api.connection.ProxiedPlayer; import net.md_5.bungee.protocol.DefinedPacket; -import net.md_5.bungee.protocol.ProtocolConstants; +@RequiredArgsConstructor(access = AccessLevel.PRIVATE) class EntityMap_1_16_2 extends EntityMap { - static final EntityMap_1_16_2 INSTANCE = new EntityMap_1_16_2(); - - EntityMap_1_16_2() - { - addRewrite( 0x00, ProtocolConstants.Direction.TO_CLIENT, true ); // Spawn Object : PacketPlayOutSpawnEntity - addRewrite( 0x01, ProtocolConstants.Direction.TO_CLIENT, true ); // Spawn Experience Orb : PacketPlayOutSpawnEntityExperienceOrb - addRewrite( 0x02, ProtocolConstants.Direction.TO_CLIENT, true ); // Spawn Mob : PacketPlayOutSpawnEntityLiving - addRewrite( 0x03, ProtocolConstants.Direction.TO_CLIENT, true ); // Spawn Painting : PacketPlayOutSpawnEntityPainting - addRewrite( 0x04, ProtocolConstants.Direction.TO_CLIENT, true ); // Spawn Player : PacketPlayOutNamedEntitySpawn - addRewrite( 0x05, ProtocolConstants.Direction.TO_CLIENT, true ); // Animation : PacketPlayOutAnimation - addRewrite( 0x08, ProtocolConstants.Direction.TO_CLIENT, true ); // Block Break Animation : PacketPlayOutBlockBreakAnimation - addRewrite( 0x1A, ProtocolConstants.Direction.TO_CLIENT, false ); // Entity Status : PacketPlayOutEntityStatus - addRewrite( 0x27, ProtocolConstants.Direction.TO_CLIENT, true ); // Entity Relative Move : PacketPlayOutRelEntityMove - addRewrite( 0x28, ProtocolConstants.Direction.TO_CLIENT, true ); // Entity Look and Relative Move : PacketPlayOutRelEntityMoveLook - addRewrite( 0x29, ProtocolConstants.Direction.TO_CLIENT, true ); // Entity Look : PacketPlayOutEntityLook - addRewrite( 0x2A, ProtocolConstants.Direction.TO_CLIENT, true ); // Entity : PacketPlayOutEntity - addRewrite( 0x37, ProtocolConstants.Direction.TO_CLIENT, true ); // Remove Entity Effect : PacketPlayOutRemoveEntityEffect - addRewrite( 0x3A, ProtocolConstants.Direction.TO_CLIENT, true ); // Entity Head Look : PacketPlayOutEntityHeadRotation - addRewrite( 0x3E, ProtocolConstants.Direction.TO_CLIENT, true ); // Camera : PacketPlayOutCamera - addRewrite( 0x44, ProtocolConstants.Direction.TO_CLIENT, true ); // Entity Metadata : PacketPlayOutEntityMetadata - addRewrite( 0x45, ProtocolConstants.Direction.TO_CLIENT, false ); // Attach Entity : PacketPlayOutAttachEntity - addRewrite( 0x46, ProtocolConstants.Direction.TO_CLIENT, true ); // Entity Velocity : PacketPlayOutEntityVelocity - addRewrite( 0x47, ProtocolConstants.Direction.TO_CLIENT, true ); // Entity Equipment : PacketPlayOutEntityEquipment - addRewrite( 0x4B, ProtocolConstants.Direction.TO_CLIENT, true ); // Set Passengers : PacketPlayOutMount - addRewrite( 0x55, ProtocolConstants.Direction.TO_CLIENT, true ); // Collect Item : PacketPlayOutCollect - addRewrite( 0x56, ProtocolConstants.Direction.TO_CLIENT, true ); // Entity Teleport : PacketPlayOutEntityTeleport - addRewrite( 0x58, ProtocolConstants.Direction.TO_CLIENT, true ); // Entity Properties : PacketPlayOutUpdateAttributes - addRewrite( 0x59, ProtocolConstants.Direction.TO_CLIENT, true ); // Entity Effect : PacketPlayOutEntityEffect - - addRewrite( 0x0E, ProtocolConstants.Direction.TO_SERVER, true ); // Use Entity : PacketPlayInUseEntity - addRewrite( 0x1C, ProtocolConstants.Direction.TO_SERVER, true ); // Entity Action : PacketPlayInEntityAction - } + static final EntityMap_1_16_2 INSTANCE_1_16_2 = new EntityMap_1_16_2( 0x04, 0x2D ); + static final EntityMap_1_16_2 INSTANCE_1_17 = new EntityMap_1_16_2( 0x04, 0x2D ); + // + private final int spawnPlayerId; + private final int spectateId; @Override @SuppressFBWarnings("DLS_DEAD_LOCAL_STORE") public void rewriteClientbound(ByteBuf packet, int oldId, int newId, int protocolVersion) { - super.rewriteClientbound( packet, oldId, newId ); - // Special cases int readerIndex = packet.readerIndex(); int packetId = DefinedPacket.readVarInt( packet ); int packetIdLength = packet.readerIndex() - readerIndex; - int jumpIndex = packet.readerIndex(); - switch ( packetId ) - { - case 0x45 /* Attach Entity : PacketPlayOutAttachEntity */: - rewriteInt( packet, oldId, newId, readerIndex + packetIdLength + 4 ); - break; - case 0x55 /* Collect Item : PacketPlayOutCollect */: - DefinedPacket.readVarInt( packet ); - rewriteVarInt( packet, oldId, newId, packet.readerIndex() ); - break; - case 0x4B /* Set Passengers : PacketPlayOutMount */: - DefinedPacket.readVarInt( packet ); - jumpIndex = packet.readerIndex(); - // Fall through on purpose to int array of IDs - case 0x36 /* Destroy Entities : PacketPlayOutEntityDestroy */: - int count = DefinedPacket.readVarInt( packet ); - int[] ids = new int[ count ]; - for ( int i = 0; i < count; i++ ) - { - ids[i] = DefinedPacket.readVarInt( packet ); - } - packet.readerIndex( jumpIndex ); - packet.writerIndex( jumpIndex ); - DefinedPacket.writeVarInt( count, packet ); - for ( int id : ids ) - { - if ( id == oldId ) - { - id = newId; - } else if ( id == newId ) - { - id = oldId; - } - DefinedPacket.writeVarInt( id, packet ); - } - break; - case 0x00 /* Spawn Object : PacketPlayOutSpawnEntity */: - DefinedPacket.readVarInt( packet ); - DefinedPacket.readUUID( packet ); - int type = DefinedPacket.readVarInt( packet ); - if ( type == 2 || type == 102 || type == 72 ) // arrow, fishing_bobber or spectral_arrow - { - if ( type == 2 || type == 72 ) // arrow or spectral_arrow - { - oldId = oldId + 1; - newId = newId + 1; - } - - packet.skipBytes( 26 ); // double, double, double, byte, byte - int position = packet.readerIndex(); - int readId = packet.readInt(); - if ( readId == oldId ) - { - packet.setInt( position, newId ); - } else if ( readId == newId ) - { - packet.setInt( position, oldId ); - } - } - break; - case 0x04 /* Spawn Player : PacketPlayOutNamedEntitySpawn */: - DefinedPacket.readVarInt( packet ); // Entity ID - int idLength = packet.readerIndex() - readerIndex - packetIdLength; - UUID uuid = DefinedPacket.readUUID( packet ); - ProxiedPlayer player; - if ( ( player = BungeeCord.getInstance().getPlayerByOfflineUUID( uuid ) ) != null ) - { - int previous = packet.writerIndex(); - packet.readerIndex( readerIndex ); - packet.writerIndex( readerIndex + packetIdLength + idLength ); - DefinedPacket.writeUUID( player.getUniqueId(), packet ); - packet.writerIndex( previous ); - } - break; - case 0x31 /* Combat Event : PacketPlayOutCombatEvent */: - int event = packet.readUnsignedByte(); - if ( event == 1 /* End Combat*/ ) - { - DefinedPacket.readVarInt( packet ); - rewriteInt( packet, oldId, newId, packet.readerIndex() ); - } else if ( event == 2 /* Entity Dead */ ) - { - int position = packet.readerIndex(); - rewriteVarInt( packet, oldId, newId, packet.readerIndex() ); - packet.readerIndex( position ); - DefinedPacket.readVarInt( packet ); - rewriteInt( packet, oldId, newId, packet.readerIndex() ); - } - break; - case 0x44 /* EntityMetadata : PacketPlayOutEntityMetadata */: - DefinedPacket.readVarInt( packet ); // Entity ID - rewriteMetaVarInt( packet, oldId + 1, newId + 1, 7, protocolVersion ); // fishing hook - rewriteMetaVarInt( packet, oldId, newId, 8, protocolVersion ); // fireworks (et al) - rewriteMetaVarInt( packet, oldId, newId, 16, protocolVersion ); // guardian beam - break; - case 0x50 /* Entity Sound Effect : PacketPlayOutEntitySound */: - DefinedPacket.readVarInt( packet ); - DefinedPacket.readVarInt( packet ); - rewriteVarInt( packet, oldId, newId, packet.readerIndex() ); - break; + if ( packetId == spawnPlayerId ) + { + DefinedPacket.readVarInt( packet ); // Entity ID + int idLength = packet.readerIndex() - readerIndex - packetIdLength; + UUID uuid = DefinedPacket.readUUID( packet ); + ProxiedPlayer player; + if ( ( player = BungeeCord.getInstance().getPlayerByOfflineUUID( uuid ) ) != null ) + { + int previous = packet.writerIndex(); + packet.readerIndex( readerIndex ); + packet.writerIndex( readerIndex + packetIdLength + idLength ); + DefinedPacket.writeUUID( player.getUniqueId(), packet ); + packet.writerIndex( previous ); + } } packet.readerIndex( readerIndex ); } @@ -163,13 +50,12 @@ public void rewriteClientbound(ByteBuf packet, int oldId, int newId, int protoco @Override public void rewriteServerbound(ByteBuf packet, int oldId, int newId) { - super.rewriteServerbound( packet, oldId, newId ); // Special cases int readerIndex = packet.readerIndex(); int packetId = DefinedPacket.readVarInt( packet ); int packetIdLength = packet.readerIndex() - readerIndex; - if ( packetId == 0x2D /* Spectate : PacketPlayInSpectate */ && !BungeeCord.getInstance().getConfig().isIpForward() ) + if ( packetId == spectateId ) { UUID uuid = DefinedPacket.readUUID( packet ); ProxiedPlayer player; diff --git a/proxy/src/main/java/net/md_5/bungee/netty/HandlerBoss.java b/proxy/src/main/java/net/md_5/bungee/netty/HandlerBoss.java index 989bfd87b9..270545f28e 100644 --- a/proxy/src/main/java/net/md_5/bungee/netty/HandlerBoss.java +++ b/proxy/src/main/java/net/md_5/bungee/netty/HandlerBoss.java @@ -81,14 +81,20 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception if ( msg instanceof HAProxyMessage ) { HAProxyMessage proxy = (HAProxyMessage) msg; - InetSocketAddress newAddress = new InetSocketAddress( proxy.sourceAddress(), proxy.sourcePort() ); - - ProxyServer.getInstance().getLogger().log( Level.FINE, "Set remote address via PROXY {0} -> {1}", new Object[] + try { - channel.getRemoteAddress(), newAddress - } ); + InetSocketAddress newAddress = new InetSocketAddress( proxy.sourceAddress(), proxy.sourcePort() ); + + ProxyServer.getInstance().getLogger().log( Level.FINE, "Set remote address via PROXY {0} -> {1}", new Object[] + { + channel.getRemoteAddress(), newAddress + } ); - channel.setRemoteAddress( newAddress ); + channel.setRemoteAddress( newAddress ); + } finally + { + proxy.release(); + } return; } diff --git a/proxy/src/main/java/net/md_5/bungee/netty/PipelineUtils.java b/proxy/src/main/java/net/md_5/bungee/netty/PipelineUtils.java index afc2c12a26..1533eadcd5 100644 --- a/proxy/src/main/java/net/md_5/bungee/netty/PipelineUtils.java +++ b/proxy/src/main/java/net/md_5/bungee/netty/PipelineUtils.java @@ -172,8 +172,8 @@ public void initChannel(Channel ch) throws Exception ch.config().setAllocator( PooledByteBufAllocator.DEFAULT ); ch.config().setWriteBufferWaterMark( MARK ); - ch.pipeline().addLast( TIMEOUT_HANDLER, new ReadTimeoutHandler( BungeeCord.getInstance().config.getTimeout(), TimeUnit.MILLISECONDS ) ); ch.pipeline().addLast( FRAME_DECODER, new Varint21FrameDecoder() ); + ch.pipeline().addLast( TIMEOUT_HANDLER, new ReadTimeoutHandler( BungeeCord.getInstance().config.getTimeout(), TimeUnit.MILLISECONDS ) ); ch.pipeline().addLast( FRAME_PREPENDER, framePrepender ); ch.pipeline().addLast( BOSS_HANDLER, new HandlerBoss() ); diff --git a/proxy/src/main/java/net/md_5/bungee/util/AddressUtil.java b/proxy/src/main/java/net/md_5/bungee/util/AddressUtil.java new file mode 100644 index 0000000000..03dabe0181 --- /dev/null +++ b/proxy/src/main/java/net/md_5/bungee/util/AddressUtil.java @@ -0,0 +1,26 @@ +package net.md_5.bungee.util; + +import java.net.Inet6Address; +import java.net.InetSocketAddress; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class AddressUtil +{ + + public static String sanitizeAddress(InetSocketAddress addr) + { + String string = addr.getHostString(); + + // Remove IPv6 scope if present + if ( addr.getAddress() instanceof Inet6Address ) + { + int strip = string.indexOf( '%' ); + return ( strip == -1 ) ? string : string.substring( 0, strip ); + } else + { + return string; + } + } +} 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 bb41b366e1..faca17faea 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 @@ -115,7 +115,7 @@ public BaseComponent[] transform(ProxiedPlayer player, boolean transformHover, B { if ( root.getExtra() != null && !root.getExtra().isEmpty() ) { - List list = Lists.newArrayList( transform( player, transformHover, root.getExtra().toArray( new BaseComponent[ root.getExtra().size() ] ) ) ); + List list = Lists.newArrayList( transform( player, transformHover, root.getExtra().toArray( new BaseComponent[ 0 ] ) ) ); root.setExtra( list ); } diff --git a/proxy/src/test/java/net/md_5/bungee/util/AddressUtilTest.java b/proxy/src/test/java/net/md_5/bungee/util/AddressUtilTest.java new file mode 100644 index 0000000000..e2a3a481d4 --- /dev/null +++ b/proxy/src/test/java/net/md_5/bungee/util/AddressUtilTest.java @@ -0,0 +1,19 @@ +package net.md_5.bungee.util; + +import java.net.InetSocketAddress; +import org.junit.Assert; +import org.junit.Test; + +public class AddressUtilTest +{ + + @Test + public void testScope() + { + InetSocketAddress addr = new InetSocketAddress( "0:0:0:0:0:0:0:1%0", 25577 ); + Assert.assertEquals( "0:0:0:0:0:0:0:1", AddressUtil.sanitizeAddress( addr ) ); + + InetSocketAddress addr2 = new InetSocketAddress( "0:0:0:0:0:0:0:1", 25577 ); + Assert.assertEquals( "0:0:0:0:0:0:0:1", AddressUtil.sanitizeAddress( addr2 ) ); + } +} diff --git a/query/pom.xml b/query/pom.xml index 3023d072b4..4212899e72 100644 --- a/query/pom.xml +++ b/query/pom.xml @@ -6,13 +6,13 @@ net.md-5 bungeecord-parent - 1.16-R0.5-SNAPSHOT + 1.17-R0.1-SNAPSHOT ../pom.xml net.md-5 bungeecord-query - 1.16-R0.5-SNAPSHOT + 1.17-R0.1-SNAPSHOT jar BungeeCord-Query diff --git a/slf4j/nb-configuration.xml b/slf4j/nb-configuration.xml new file mode 100644 index 0000000000..7e46592400 --- /dev/null +++ b/slf4j/nb-configuration.xml @@ -0,0 +1,31 @@ + + + + + + project + NEW_LINE + NEW_LINE + NEW_LINE + true + true + true + true + true + true + true + true + true + true + + diff --git a/slf4j/pom.xml b/slf4j/pom.xml new file mode 100644 index 0000000000..fd365ed0b0 --- /dev/null +++ b/slf4j/pom.xml @@ -0,0 +1,35 @@ + + + 4.0.0 + + + net.md-5 + bungeecord-parent + 1.17-R0.1-SNAPSHOT + ../pom.xml + + + net.md-5 + bungeecord-slf4j + 1.17-R0.1-SNAPSHOT + jar + + BungeeCord-SLF4J + Wrapper over SLF4J for BungeeCord purposes. + + + true + true + true + + + + + org.slf4j + slf4j-api + 1.7.30 + compile + + + diff --git a/slf4j/src/main/java/org/slf4j/impl/JDK14LoggerAdapter.java b/slf4j/src/main/java/org/slf4j/impl/JDK14LoggerAdapter.java new file mode 100644 index 0000000000..7cfafc8861 --- /dev/null +++ b/slf4j/src/main/java/org/slf4j/impl/JDK14LoggerAdapter.java @@ -0,0 +1,694 @@ +/** + * Copyright (c) 2004-2011 QOS.ch + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +package org.slf4j.impl; + +import java.util.logging.Level; +import java.util.logging.LogRecord; + +import org.slf4j.Logger; +import org.slf4j.Marker; +import org.slf4j.event.EventConstants; +import org.slf4j.event.LoggingEvent; +import org.slf4j.helpers.FormattingTuple; +import org.slf4j.helpers.MarkerIgnoringBase; +import org.slf4j.helpers.MessageFormatter; +import org.slf4j.spi.LocationAwareLogger; + +/** + * A wrapper over {@link java.util.logging.Logger java.util.logging.Logger} in + * conformity with the {@link Logger} interface. Note that the logging levels + * mentioned in this class refer to those defined in the java.util.logging + * package. + * + * @author Ceki Gülcü + * @author Peter Royal + */ +public final class JDK14LoggerAdapter extends MarkerIgnoringBase implements LocationAwareLogger { + + private static final long serialVersionUID = -8053026990503422791L; + + transient final java.util.logging.Logger logger; + + // WARN: JDK14LoggerAdapter constructor should have only package access so + // that only JDK14LoggerFactory be able to create one. + JDK14LoggerAdapter(java.util.logging.Logger logger) { + this.logger = logger; + this.name = logger.getName(); + } + + /** + * Is this logger instance enabled for the FINEST level? + * + * @return True if this Logger is enabled for level FINEST, false otherwise. + */ + public boolean isTraceEnabled() { + return logger.isLoggable(Level.FINEST); + } + + /** + * Log a message object at level FINEST. + * + * @param msg + * - the message object to be logged + */ + public void trace(String msg) { + if (logger.isLoggable(Level.FINEST)) { + log(SELF, Level.FINEST, msg, null); + } + } + + /** + * Log a message at level FINEST according to the specified format and + * argument. + * + *

+ * This form avoids superfluous object creation when the logger is disabled + * for level FINEST. + *

+ * + * @param format + * the format string + * @param arg + * the argument + */ + public void trace(String format, Object arg) { + if (logger.isLoggable(Level.FINEST)) { + FormattingTuple ft = MessageFormatter.format(format, arg); + log(SELF, Level.FINEST, ft.getMessage(), ft.getThrowable()); + } + } + + /** + * Log a message at level FINEST according to the specified format and + * arguments. + * + *

+ * This form avoids superfluous object creation when the logger is disabled + * for the FINEST level. + *

+ * + * @param format + * the format string + * @param arg1 + * the first argument + * @param arg2 + * the second argument + */ + public void trace(String format, Object arg1, Object arg2) { + if (logger.isLoggable(Level.FINEST)) { + FormattingTuple ft = MessageFormatter.format(format, arg1, arg2); + log(SELF, Level.FINEST, ft.getMessage(), ft.getThrowable()); + } + } + + /** + * Log a message at level FINEST according to the specified format and + * arguments. + * + *

+ * This form avoids superfluous object creation when the logger is disabled + * for the FINEST level. + *

+ * + * @param format + * the format string + * @param argArray + * an array of arguments + */ + public void trace(String format, Object... argArray) { + if (logger.isLoggable(Level.FINEST)) { + FormattingTuple ft = MessageFormatter.arrayFormat(format, argArray); + log(SELF, Level.FINEST, ft.getMessage(), ft.getThrowable()); + } + } + + /** + * Log an exception (throwable) at level FINEST with an accompanying message. + * + * @param msg + * the message accompanying the exception + * @param t + * the exception (throwable) to log + */ + public void trace(String msg, Throwable t) { + if (logger.isLoggable(Level.FINEST)) { + log(SELF, Level.FINEST, msg, t); + } + } + + /** + * Is this logger instance enabled for the FINE level? + * + * @return True if this Logger is enabled for level FINE, false otherwise. + */ + public boolean isDebugEnabled() { + return logger.isLoggable(Level.FINE); + } + + /** + * Log a message object at level FINE. + * + * @param msg + * - the message object to be logged + */ + public void debug(String msg) { + if (logger.isLoggable(Level.FINE)) { + log(SELF, Level.FINE, msg, null); + } + } + + /** + * Log a message at level FINE according to the specified format and argument. + * + *

+ * This form avoids superfluous object creation when the logger is disabled + * for level FINE. + *

+ * + * @param format + * the format string + * @param arg + * the argument + */ + public void debug(String format, Object arg) { + if (logger.isLoggable(Level.FINE)) { + FormattingTuple ft = MessageFormatter.format(format, arg); + log(SELF, Level.FINE, ft.getMessage(), ft.getThrowable()); + } + } + + /** + * Log a message at level FINE according to the specified format and + * arguments. + * + *

+ * This form avoids superfluous object creation when the logger is disabled + * for the FINE level. + *

+ * + * @param format + * the format string + * @param arg1 + * the first argument + * @param arg2 + * the second argument + */ + public void debug(String format, Object arg1, Object arg2) { + if (logger.isLoggable(Level.FINE)) { + FormattingTuple ft = MessageFormatter.format(format, arg1, arg2); + log(SELF, Level.FINE, ft.getMessage(), ft.getThrowable()); + } + } + + /** + * Log a message at level FINE according to the specified format and + * arguments. + * + *

+ * This form avoids superfluous object creation when the logger is disabled + * for the FINE level. + *

+ * + * @param format + * the format string + * @param argArray + * an array of arguments + */ + public void debug(String format, Object... argArray) { + if (logger.isLoggable(Level.FINE)) { + FormattingTuple ft = MessageFormatter.arrayFormat(format, argArray); + log(SELF, Level.FINE, ft.getMessage(), ft.getThrowable()); + } + } + + /** + * Log an exception (throwable) at level FINE with an accompanying message. + * + * @param msg + * the message accompanying the exception + * @param t + * the exception (throwable) to log + */ + public void debug(String msg, Throwable t) { + if (logger.isLoggable(Level.FINE)) { + log(SELF, Level.FINE, msg, t); + } + } + + /** + * Is this logger instance enabled for the INFO level? + * + * @return True if this Logger is enabled for the INFO level, false otherwise. + */ + public boolean isInfoEnabled() { + return logger.isLoggable(Level.INFO); + } + + /** + * Log a message object at the INFO level. + * + * @param msg + * - the message object to be logged + */ + public void info(String msg) { + if (logger.isLoggable(Level.INFO)) { + log(SELF, Level.INFO, msg, null); + } + } + + /** + * Log a message at level INFO according to the specified format and argument. + * + *

+ * This form avoids superfluous object creation when the logger is disabled + * for the INFO level. + *

+ * + * @param format + * the format string + * @param arg + * the argument + */ + public void info(String format, Object arg) { + if (logger.isLoggable(Level.INFO)) { + FormattingTuple ft = MessageFormatter.format(format, arg); + log(SELF, Level.INFO, ft.getMessage(), ft.getThrowable()); + } + } + + /** + * Log a message at the INFO level according to the specified format and + * arguments. + * + *

+ * This form avoids superfluous object creation when the logger is disabled + * for the INFO level. + *

+ * + * @param format + * the format string + * @param arg1 + * the first argument + * @param arg2 + * the second argument + */ + public void info(String format, Object arg1, Object arg2) { + if (logger.isLoggable(Level.INFO)) { + FormattingTuple ft = MessageFormatter.format(format, arg1, arg2); + log(SELF, Level.INFO, ft.getMessage(), ft.getThrowable()); + } + } + + /** + * Log a message at level INFO according to the specified format and + * arguments. + * + *

+ * This form avoids superfluous object creation when the logger is disabled + * for the INFO level. + *

+ * + * @param format + * the format string + * @param argArray + * an array of arguments + */ + public void info(String format, Object... argArray) { + if (logger.isLoggable(Level.INFO)) { + FormattingTuple ft = MessageFormatter.arrayFormat(format, argArray); + log(SELF, Level.INFO, ft.getMessage(), ft.getThrowable()); + } + } + + /** + * Log an exception (throwable) at the INFO level with an accompanying + * message. + * + * @param msg + * the message accompanying the exception + * @param t + * the exception (throwable) to log + */ + public void info(String msg, Throwable t) { + if (logger.isLoggable(Level.INFO)) { + log(SELF, Level.INFO, msg, t); + } + } + + /** + * Is this logger instance enabled for the WARNING level? + * + * @return True if this Logger is enabled for the WARNING level, false + * otherwise. + */ + public boolean isWarnEnabled() { + return logger.isLoggable(Level.WARNING); + } + + /** + * Log a message object at the WARNING level. + * + * @param msg + * - the message object to be logged + */ + public void warn(String msg) { + if (logger.isLoggable(Level.WARNING)) { + log(SELF, Level.WARNING, msg, null); + } + } + + /** + * Log a message at the WARNING level according to the specified format and + * argument. + * + *

+ * This form avoids superfluous object creation when the logger is disabled + * for the WARNING level. + *

+ * + * @param format + * the format string + * @param arg + * the argument + */ + public void warn(String format, Object arg) { + if (logger.isLoggable(Level.WARNING)) { + FormattingTuple ft = MessageFormatter.format(format, arg); + log(SELF, Level.WARNING, ft.getMessage(), ft.getThrowable()); + } + } + + /** + * Log a message at the WARNING level according to the specified format and + * arguments. + * + *

+ * This form avoids superfluous object creation when the logger is disabled + * for the WARNING level. + *

+ * + * @param format + * the format string + * @param arg1 + * the first argument + * @param arg2 + * the second argument + */ + public void warn(String format, Object arg1, Object arg2) { + if (logger.isLoggable(Level.WARNING)) { + FormattingTuple ft = MessageFormatter.format(format, arg1, arg2); + log(SELF, Level.WARNING, ft.getMessage(), ft.getThrowable()); + } + } + + /** + * Log a message at level WARNING according to the specified format and + * arguments. + * + *

+ * This form avoids superfluous object creation when the logger is disabled + * for the WARNING level. + *

+ * + * @param format + * the format string + * @param argArray + * an array of arguments + */ + public void warn(String format, Object... argArray) { + if (logger.isLoggable(Level.WARNING)) { + FormattingTuple ft = MessageFormatter.arrayFormat(format, argArray); + log(SELF, Level.WARNING, ft.getMessage(), ft.getThrowable()); + } + } + + /** + * Log an exception (throwable) at the WARNING level with an accompanying + * message. + * + * @param msg + * the message accompanying the exception + * @param t + * the exception (throwable) to log + */ + public void warn(String msg, Throwable t) { + if (logger.isLoggable(Level.WARNING)) { + log(SELF, Level.WARNING, msg, t); + } + } + + /** + * Is this logger instance enabled for level SEVERE? + * + * @return True if this Logger is enabled for level SEVERE, false otherwise. + */ + public boolean isErrorEnabled() { + return logger.isLoggable(Level.SEVERE); + } + + /** + * Log a message object at the SEVERE level. + * + * @param msg + * - the message object to be logged + */ + public void error(String msg) { + if (logger.isLoggable(Level.SEVERE)) { + log(SELF, Level.SEVERE, msg, null); + } + } + + /** + * Log a message at the SEVERE level according to the specified format and + * argument. + * + *

+ * This form avoids superfluous object creation when the logger is disabled + * for the SEVERE level. + *

+ * + * @param format + * the format string + * @param arg + * the argument + */ + public void error(String format, Object arg) { + if (logger.isLoggable(Level.SEVERE)) { + FormattingTuple ft = MessageFormatter.format(format, arg); + log(SELF, Level.SEVERE, ft.getMessage(), ft.getThrowable()); + } + } + + /** + * Log a message at the SEVERE level according to the specified format and + * arguments. + * + *

+ * This form avoids superfluous object creation when the logger is disabled + * for the SEVERE level. + *

+ * + * @param format + * the format string + * @param arg1 + * the first argument + * @param arg2 + * the second argument + */ + public void error(String format, Object arg1, Object arg2) { + if (logger.isLoggable(Level.SEVERE)) { + FormattingTuple ft = MessageFormatter.format(format, arg1, arg2); + log(SELF, Level.SEVERE, ft.getMessage(), ft.getThrowable()); + } + } + + /** + * Log a message at level SEVERE according to the specified format and + * arguments. + * + *

+ * This form avoids superfluous object creation when the logger is disabled + * for the SEVERE level. + *

+ * + * @param format + * the format string + * @param arguments + * an array of arguments + */ + public void error(String format, Object... arguments) { + if (logger.isLoggable(Level.SEVERE)) { + FormattingTuple ft = MessageFormatter.arrayFormat(format, arguments); + log(SELF, Level.SEVERE, ft.getMessage(), ft.getThrowable()); + } + } + + /** + * Log an exception (throwable) at the SEVERE level with an accompanying + * message. + * + * @param msg + * the message accompanying the exception + * @param t + * the exception (throwable) to log + */ + public void error(String msg, Throwable t) { + if (logger.isLoggable(Level.SEVERE)) { + log(SELF, Level.SEVERE, msg, t); + } + } + + /** + * Log the message at the specified level with the specified throwable if any. + * This method creates a LogRecord and fills in caller date before calling + * this instance's JDK14 logger. + * + * See bug report #13 for more details. + * + * @param level + * @param msg + * @param t + */ + private void log(String callerFQCN, Level level, String msg, Throwable t) { + // millis and thread are filled by the constructor + LogRecord record = new LogRecord(level, msg); + record.setLoggerName(getName()); + record.setThrown(t); + // Note: parameters in record are not set because SLF4J only + // supports a single formatting style + fillCallerData(callerFQCN, record); + logger.log(record); + } + + static String SELF = JDK14LoggerAdapter.class.getName(); + static String SUPER = MarkerIgnoringBase.class.getName(); + + /** + * Fill in caller data if possible. + * + * @param record + * The record to update + */ + final private void fillCallerData(String callerFQCN, LogRecord record) { + StackTraceElement[] steArray = new Throwable().getStackTrace(); + + int selfIndex = -1; + for (int i = 0; i < steArray.length; i++) { + final String className = steArray[i].getClassName(); + if (className.equals(callerFQCN) || className.equals(SUPER)) { + selfIndex = i; + break; + } + } + + int found = -1; + for (int i = selfIndex + 1; i < steArray.length; i++) { + final String className = steArray[i].getClassName(); + if (!(className.equals(callerFQCN) || className.equals(SUPER))) { + found = i; + break; + } + } + + if (found != -1) { + StackTraceElement ste = steArray[found]; + // setting the class name has the side effect of setting + // the needToInferCaller variable to false. + record.setSourceClassName(ste.getClassName()); + record.setSourceMethodName(ste.getMethodName()); + } + } + + public void log(Marker marker, String callerFQCN, int level, String message, Object[] argArray, Throwable t) { + Level julLevel = slf4jLevelIntToJULLevel(level); + // the logger.isLoggable check avoids the unconditional + // construction of location data for disabled log + // statements. As of 2008-07-31, callers of this method + // do not perform this check. See also + // http://jira.qos.ch/browse/SLF4J-81 + if (logger.isLoggable(julLevel)) { + log(callerFQCN, julLevel, message, t); + } + } + + private Level slf4jLevelIntToJULLevel(int slf4jLevelInt) { + Level julLevel; + switch (slf4jLevelInt) { + case LocationAwareLogger.TRACE_INT: + julLevel = Level.FINEST; + break; + case LocationAwareLogger.DEBUG_INT: + julLevel = Level.FINE; + break; + case LocationAwareLogger.INFO_INT: + julLevel = Level.INFO; + break; + case LocationAwareLogger.WARN_INT: + julLevel = Level.WARNING; + break; + case LocationAwareLogger.ERROR_INT: + julLevel = Level.SEVERE; + break; + default: + throw new IllegalStateException("Level number " + slf4jLevelInt + " is not recognized."); + } + return julLevel; + } + + /** + * @since 1.7.15 + */ + public void log(LoggingEvent event) { + Level julLevel = slf4jLevelIntToJULLevel(event.getLevel().toInt()); + if (logger.isLoggable(julLevel)) { + LogRecord record = eventToRecord(event, julLevel); + logger.log(record); + } + } + + private LogRecord eventToRecord(LoggingEvent event, Level julLevel) { + String format = event.getMessage(); + Object[] arguments = event.getArgumentArray(); + FormattingTuple ft = MessageFormatter.arrayFormat(format, arguments); + if (ft.getThrowable() != null && event.getThrowable() != null) { + throw new IllegalArgumentException("both last element in argument array and last argument are of type Throwable"); + } + + Throwable t = event.getThrowable(); + if (ft.getThrowable() != null) { + t = ft.getThrowable(); + throw new IllegalStateException("fix above code"); + } + + LogRecord record = new LogRecord(julLevel, ft.getMessage()); + record.setLoggerName(event.getLoggerName()); + record.setMillis(event.getTimeStamp()); + record.setSourceClassName(EventConstants.NA_SUBST); + record.setSourceMethodName(EventConstants.NA_SUBST); + + record.setThrown(t); + return record; + } +} diff --git a/slf4j/src/main/java/org/slf4j/impl/JDK14LoggerFactory.java b/slf4j/src/main/java/org/slf4j/impl/JDK14LoggerFactory.java new file mode 100644 index 0000000000..2d6eaaf8ad --- /dev/null +++ b/slf4j/src/main/java/org/slf4j/impl/JDK14LoggerFactory.java @@ -0,0 +1,73 @@ +/** + * Copyright (c) 2004-2011 QOS.ch + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +package org.slf4j.impl; + +import org.slf4j.Logger; +import org.slf4j.ILoggerFactory; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +/** + * JDK14LoggerFactory is an implementation of {@link ILoggerFactory} returning + * the appropriately named {@link JDK14LoggerAdapter} instance. + * + * @author Ceki Gülcü + */ +public class JDK14LoggerFactory implements ILoggerFactory { + + // key: name (String), value: a JDK14LoggerAdapter; + ConcurrentMap loggerMap; + public static java.util.logging.Logger LOGGER; // BungeeCord + + public JDK14LoggerFactory() { + loggerMap = new ConcurrentHashMap(); + // ensure jul initialization. see SLF4J-359 + // note that call to java.util.logging.LogManager.getLogManager() fails on the Google App Engine platform. See SLF4J-363 + java.util.logging.Logger.getLogger(""); + } + + /* + * (non-Javadoc) + * + * @see org.slf4j.ILoggerFactory#getLogger(java.lang.String) + */ + public Logger getLogger(String name) { + // the root logger is called "" in JUL + if (name.equalsIgnoreCase(Logger.ROOT_LOGGER_NAME)) { + name = ""; + } + + Logger slf4jLogger = loggerMap.get(name); + if (slf4jLogger != null) + return slf4jLogger; + else { + java.util.logging.Logger julLogger = LOGGER; // BungeeCord - TODO: per-plugin loggers + Logger newInstance = new JDK14LoggerAdapter(julLogger); + Logger oldInstance = loggerMap.putIfAbsent(name, newInstance); + return oldInstance == null ? newInstance : oldInstance; + } + } +} diff --git a/slf4j/src/main/java/org/slf4j/impl/StaticLoggerBinder.java b/slf4j/src/main/java/org/slf4j/impl/StaticLoggerBinder.java new file mode 100644 index 0000000000..ebf8ae11ac --- /dev/null +++ b/slf4j/src/main/java/org/slf4j/impl/StaticLoggerBinder.java @@ -0,0 +1,80 @@ +/** + * Copyright (c) 2004-2011 QOS.ch + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +package org.slf4j.impl; + +import org.slf4j.ILoggerFactory; +import org.slf4j.LoggerFactory; +import org.slf4j.spi.LoggerFactoryBinder; + +/** + * The binding of {@link LoggerFactory} class with an actual instance of + * {@link ILoggerFactory} is performed using information returned by this class. + * + * @author Ceki Gülcü + */ +public class StaticLoggerBinder implements LoggerFactoryBinder { + + /** + * The unique instance of this class. + * + */ + private static final StaticLoggerBinder SINGLETON = new StaticLoggerBinder(); + + /** + * Return the singleton of this class. + * + * @return the StaticLoggerBinder singleton + */ + public static final StaticLoggerBinder getSingleton() { + return SINGLETON; + } + + /** + * Declare the version of the SLF4J API this implementation is compiled against. + * The value of this field is modified with each major release. + */ + // to avoid constant folding by the compiler, this field must *not* be final + public static String REQUESTED_API_VERSION = "1.6.99"; // !final + + private static final String loggerFactoryClassStr = org.slf4j.impl.JDK14LoggerFactory.class.getName(); + + /** The ILoggerFactory instance returned by the {@link #getLoggerFactory} method + * should always be the same object + */ + private final ILoggerFactory loggerFactory; + + private StaticLoggerBinder() { + // Note: JCL gets substituted at build time by an appropriate Ant task + loggerFactory = new org.slf4j.impl.JDK14LoggerFactory(); + } + + public ILoggerFactory getLoggerFactory() { + return loggerFactory; + } + + public String getLoggerFactoryClassStr() { + return loggerFactoryClassStr; + } +} diff --git a/slf4j/src/main/java/org/slf4j/impl/StaticMDCBinder.java b/slf4j/src/main/java/org/slf4j/impl/StaticMDCBinder.java new file mode 100644 index 0000000000..0a1dcb4c66 --- /dev/null +++ b/slf4j/src/main/java/org/slf4j/impl/StaticMDCBinder.java @@ -0,0 +1,68 @@ +/** + * Copyright (c) 2004-2011 QOS.ch + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +package org.slf4j.impl; + +import org.slf4j.helpers.BasicMDCAdapter; +import org.slf4j.spi.MDCAdapter; + +/** + * This implementation is bound to {@link BasicMDCAdapter}. + * + * @author Ceki Gülcü + */ +public class StaticMDCBinder { + + /** + * The unique instance of this class. + */ + public static final StaticMDCBinder SINGLETON = new StaticMDCBinder(); + + private StaticMDCBinder() { + } + + /** + * Return the singleton of this class. + * + * @return the StaticMDCBinder singleton + * @since 1.7.14 + */ + public static final StaticMDCBinder getSingleton() { + return SINGLETON; + } + + /** + * Currently this method always returns an instance of + * {@link BasicMDCAdapter}. + */ + public MDCAdapter getMDCA() { + // note that this method is invoked only from within the static initializer of + // the org.slf4j.MDC class. + return new BasicMDCAdapter(); + } + + public String getMDCAdapterClassStr() { + return BasicMDCAdapter.class.getName(); + } +} diff --git a/slf4j/src/main/java/org/slf4j/impl/StaticMarkerBinder.java b/slf4j/src/main/java/org/slf4j/impl/StaticMarkerBinder.java new file mode 100644 index 0000000000..21a48df6ab --- /dev/null +++ b/slf4j/src/main/java/org/slf4j/impl/StaticMarkerBinder.java @@ -0,0 +1,77 @@ +/** + * Copyright (c) 2004-2011 QOS.ch + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +package org.slf4j.impl; + +import org.slf4j.IMarkerFactory; +import org.slf4j.MarkerFactory; +import org.slf4j.helpers.BasicMarkerFactory; +import org.slf4j.spi.MarkerFactoryBinder; + +/** + * + * The binding of {@link MarkerFactory} class with an actual instance of + * {@link IMarkerFactory} is performed using information returned by this class. + * + * @author Ceki Gülcü + */ +public class StaticMarkerBinder implements MarkerFactoryBinder { + + /** + * The unique instance of this class. + */ + public static final StaticMarkerBinder SINGLETON = new StaticMarkerBinder(); + + final IMarkerFactory markerFactory = new BasicMarkerFactory(); + + private StaticMarkerBinder() { + } + + /** + * Return the singleton of this class. + * + * @return the StaticMarkerBinder singleton + * @since 1.7.14 + */ + public static StaticMarkerBinder getSingleton() { + return SINGLETON; + } + + /** + * Currently this method always returns an instance of + * {@link BasicMarkerFactory}. + */ + public IMarkerFactory getMarkerFactory() { + return markerFactory; + } + + /** + * Currently, this method returns the class name of + * {@link BasicMarkerFactory}. + */ + public String getMarkerFactoryClassStr() { + return BasicMarkerFactory.class.getName(); + } + +}