32 Commits

Author SHA1 Message Date
md_5
edc5b4dc91 Close #656 - fix find filter. 2013-10-11 10:24:55 +11:00
md_5
220a95aece We cannot throttle like this if we want 1.7 compat, lets disable it until we work on a more compatible one. 2013-10-10 07:25:20 +11:00
md_5
4685099808 Close #564 adding a blank arg is a silly idea 2013-10-09 22:37:27 +11:00
md-5
6c14f40108 Reduce the time we wait for legacy pings. 2013-10-08 09:06:28 +11:00
md_5
b041d84063 Null check plugin input for servers 2013-10-07 16:55:29 +11:00
md_5
a9d3d9461f Mojang nerfed tab lists :( 2013-10-06 08:42:52 +11:00
md_5
3fc7064997 Add missing setters for handshake. 2013-10-05 09:50:20 +10:00
md_5
80001aa1f0 UDP + Java + IPV6 != Friends 2013-09-30 17:58:02 +10:00
marvin
a0d94282f6 Add PlayerHandshakeEvent which allows changing of versions and online mode status amongst other things. 2013-09-30 09:22:49 +10:00
md_5
33e11f4c44 Allow for iterables to be CSV-ified 2013-09-29 18:49:20 +10:00
md_5
b541e7aa76 Custom glist formatting 2013-09-29 18:45:11 +10:00
zaiyers
dd06937a3b changes to tab completion
* PacketCBTabComplete: options for completion should be seperated by
NUL
 * PluginManager: append an empty argument to arguments if command ends
with a whitespace (this will match all suggestions)
 * PlayerCommand: suggest only matching players instead of all players
2013-09-29 09:37:39 +10:00
md_5
891dc87b16 Allow unrecognised command line args 2013-09-28 21:00:38 +10:00
md_5
8e77cb35ff Use JDK map for throttle 2013-09-28 18:32:39 +10:00
md_5
59b32a8621 Remove access from PendingConnection interface 2013-09-28 17:37:30 +10:00
md_5
02324206e3 Clean up packets a tad 2013-09-28 17:03:33 +10:00
md_5
73ce828e6e [#637] - Fix resource bundle resolution 2013-09-26 09:24:30 +10:00
md_5
79d04bec2e [#582] Widen synchronized block for packet queue. 2013-09-26 09:20:52 +10:00
md_5
cbcd874d47 Close #626 - command line argument for version. Also refactors into a bootstrap which warns users when not using Java 7! 2013-09-25 17:21:03 +10:00
md_5
09f123ce9a guery -> query 2013-09-24 17:50:44 +10:00
md_5
0a5f8556fe Add config saving 2013-09-24 12:14:47 +10:00
md_5
103a509f26 Fix access of yaml config 2013-09-24 12:11:04 +10:00
md_5
32a5271dc3 Implement basic udp query to close #185 2013-09-24 10:09:55 +10:00
md_5
14389eb370 Use correct main class 2013-09-23 10:30:41 +10:00
md_5
a8b6a6b4aa Finish basic Yaml configuration API, complete with unit tests. Needs a lot of work with regards to how sections are handled, open to massive improvements from anyone that has more know-how. 2013-09-23 10:28:30 +10:00
md_5
8133304cce Use = for properties 2013-09-22 17:37:06 +10:00
md_5
3e8c21a485 Add specific exception for bad packets. 2013-09-21 16:57:17 +10:00
Matty Southall
f12dcc72d9 Fix compile error when compiling on OS X 2013-09-21 10:55:39 +10:00
md_5
a7a32509c7 find * -type f -print0 | xargs -0 sed -i 's/1.6.2/1.6.4/g' 2013-09-20 19:51:57 +10:00
md_5
703a393888 Procol -> Protocol. Fix typo, thanks @libraryaddict 2013-09-20 15:41:30 +10:00
md_5
3c961cd5d9 1.6.4 - MOJANG 2013-09-20 08:23:06 +10:00
md_5
12ee68a315 Update to 1.6.3 2013-09-19 17:41:01 +10:00
46 changed files with 803 additions and 246 deletions

View File

@@ -6,13 +6,13 @@
<parent> <parent>
<groupId>net.md-5</groupId> <groupId>net.md-5</groupId>
<artifactId>bungeecord-parent</artifactId> <artifactId>bungeecord-parent</artifactId>
<version>1.6.2-SNAPSHOT</version> <version>1.6.4-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>
<groupId>net.md-5</groupId> <groupId>net.md-5</groupId>
<artifactId>bungeecord-api</artifactId> <artifactId>bungeecord-api</artifactId>
<version>1.6.2-SNAPSHOT</version> <version>1.6.4-SNAPSHOT</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>BungeeCord-API</name> <name>BungeeCord-API</name>
@@ -25,6 +25,12 @@
<version>14.0.1</version> <version>14.0.1</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-config</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency> <dependency>
<groupId>net.md-5</groupId> <groupId>net.md-5</groupId>
<artifactId>bungeecord-event</artifactId> <artifactId>bungeecord-event</artifactId>
@@ -37,11 +43,5 @@
<version>${project.version}</version> <version>${project.version}</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.12</version>
<scope>compile</scope>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@@ -53,7 +53,7 @@ public abstract class ProxyServer
* *
* @return the localized string * @return the localized string
*/ */
public abstract String getTranslation(String name); public abstract String getTranslation(String name, Object... args);
/** /**
* Gets the main logger which can be used as a suitable replacement for * Gets the main logger which can be used as a suitable replacement for

View File

@@ -61,4 +61,12 @@ public class ListenerInfo
* server (force default server). * server (force default server).
*/ */
private final boolean pingPassthrough; private final boolean pingPassthrough;
/**
* What port to run udp query on.
*/
private final int queryPort;
/**
* Whether to enable udp query.
*/
private final boolean queryEnabled;
} }

View File

@@ -14,26 +14,26 @@ public interface PendingConnection extends Connection
* *
* @return the requested username, or null if not set * @return the requested username, or null if not set
*/ */
public String getName(); String getName();
/** /**
* Get the numerical client version of the player attempting to log in. * Get the numerical client version of the player attempting to log in.
* *
* @return the protocol version of the remote client * @return the protocol version of the remote client
*/ */
public byte getVersion(); byte getVersion();
/** /**
* Get the requested virtual host that the client tried to connect to. * Get the requested virtual host that the client tried to connect to.
* *
* @return request virtual host or null if invalid / not specified. * @return request virtual host or null if invalid / not specified.
*/ */
public InetSocketAddress getVirtualHost(); InetSocketAddress getVirtualHost();
/** /**
* Get the listener that accepted this connection. * Get the listener that accepted this connection.
* *
* @return the accepting listener * @return the accepting listener
*/ */
public ListenerInfo getListener(); ListenerInfo getListener();
} }

View File

@@ -0,0 +1,34 @@
package net.md_5.bungee.api.event;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import net.md_5.bungee.api.connection.PendingConnection;
import net.md_5.bungee.protocol.packet.Packet2Handshake;
import net.md_5.bungee.api.plugin.Event;
/**
* Event called to represent a player first making their presence and username
* known.
*/
@Data
@ToString(callSuper = false)
@EqualsAndHashCode(callSuper = false)
public class PlayerHandshakeEvent extends Event
{
/**
* Connection attempting to login.
*/
private final PendingConnection connection;
/**
* The handshake.
*/
private final Packet2Handshake handshake;
public PlayerHandshakeEvent(PendingConnection connection, Packet2Handshake handshake)
{
this.connection = connection;
this.handshake = handshake;
}
}

View File

@@ -2,6 +2,7 @@ package net.md_5.bungee.api.event;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.NonNull;
import lombok.ToString; import lombok.ToString;
import net.md_5.bungee.api.config.ServerInfo; import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.connection.ProxiedPlayer; import net.md_5.bungee.api.connection.ProxiedPlayer;
@@ -21,6 +22,7 @@ public class ServerConnectEvent extends Event implements Cancellable
/** /**
* Server the player will be connected to. * Server the player will be connected to.
*/ */
@NonNull
private ServerInfo target; private ServerInfo target;
/** /**
* Cancelled state. * Cancelled state.

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<project-shared-configuration>
<!--
This file contains additional configuration written by modules in the NetBeans IDE.
The configuration is intended to be shared among all the users of project and
therefore it is assumed to be part of version control checkout.
Without this configuration present, some functionality in the IDE may be limited or fail altogether.
-->
<properties xmlns="http://www.netbeans.org/ns/maven-properties-data/1">
<!--
Properties that influence various parts of the IDE, especially code formatting and the like.
You can copy and paste the single properties, into the pom.xml file and the IDE will pick them up.
That way multiple projects can share the same settings (useful for formatting rules for example).
Any value defined here will override the pom.xml file value but is only applicable to the current project.
-->
<org-netbeans-modules-editor-indent.CodeStyle.usedProfile>project</org-netbeans-modules-editor-indent.CodeStyle.usedProfile>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.classDeclBracePlacement>NEW_LINE</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.classDeclBracePlacement>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.otherBracePlacement>NEW_LINE</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.otherBracePlacement>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.methodDeclBracePlacement>NEW_LINE</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.methodDeclBracePlacement>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinMethodCallParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinMethodCallParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSwitchParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSwitchParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinCatchParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinCatchParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinTryParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinTryParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSynchronizedParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSynchronizedParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinArrayInitBrackets>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinArrayInitBrackets>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinWhileParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinWhileParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinIfParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinIfParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinForParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinForParens>
</properties>
</project-shared-configuration>

97
bootstrap/pom.xml Normal file
View File

@@ -0,0 +1,97 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-parent</artifactId>
<version>1.6.4-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-bootstrap</artifactId>
<version>1.6.4-SNAPSHOT</version>
<packaging>jar</packaging>
<name>BungeeCord-Bootstrap</name>
<description>Java 1.6 loader for BungeeCord</description>
<dependencies>
<dependency>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-proxy</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>net.sf.jopt-simple</groupId>
<artifactId>jopt-simple</artifactId>
<version>4.5</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<finalName>BungeeCord</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<!-- Don't deploy proxy to maven repo, only APIs -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<archive>
<manifestEntries>
<Main-Class>net.md_5.bungee.Bootstrap</Main-Class>
<Implementation-Version>${describe}</Implementation-Version>
<Specification-Version>${maven.build.timestamp}</Specification-Version>
</manifestEntries>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
<configuration>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>**/*.java</exclude>
<exclude>**/*.SF</exclude>
<exclude>**/*.DSA</exclude>
</excludes>
</filter>
</filters>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,81 @@
package net.md_5.bungee;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.List;
import java.util.concurrent.TimeUnit;
import joptsimple.OptionParser;
import joptsimple.OptionSet;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.command.ConsoleCommandSender;
public class Bootstrap
{
private static List<String> list(String... params)
{
return Arrays.asList( params );
}
/**
* Starts a new instance of BungeeCord.
*
* @param args command line arguments, currently none are used
* @throws Exception when the server cannot be started
*/
public static void main(String[] args) throws Exception
{
OptionParser parser = new OptionParser();
parser.allowsUnrecognizedOptions();
parser.acceptsAll( list( "v", "version" ) );
OptionSet options = parser.parse( args );
if ( options.has( "version" ) )
{
System.out.println( Bootstrap.class.getPackage().getImplementationVersion() );
return;
}
if ( !System.getProperty( "java.version" ).startsWith( "1.7" ) )
{
System.err.println( "*** ERROR *** BungeeCord requires Java 7 to function!" );
return;
}
if ( BungeeCord.class.getPackage().getSpecificationVersion() != null )
{
Calendar deadline = Calendar.getInstance();
deadline.add( Calendar.WEEK_OF_YEAR, 2 );
if ( Calendar.getInstance().after( new SimpleDateFormat( "yyyyMMdd" ).parse( BungeeCord.class.getPackage().getSpecificationVersion() ) ) )
{
System.err.println( "*** Warning, this build is outdated ***" );
System.err.println( "*** Please download a new build from http://ci.md-5.net/job/BungeeCord ***" );
System.err.println( "*** You will get NO support regarding this build ***" );
System.err.println( "*** Server will start in 30 seconds ***" );
Thread.sleep( TimeUnit.SECONDS.toMillis( 30 ) );
}
}
System.setProperty( "java.net.preferIPv4Stack", "true" );
BungeeCord bungee = new BungeeCord();
ProxyServer.setInstance( bungee );
bungee.getLogger().info( "Enabled BungeeCord version " + bungee.getVersion() );
bungee.start();
while ( bungee.isRunning )
{
String line = bungee.getConsoleReader().readLine( ">" );
if ( line != null )
{
if ( !bungee.getPluginManager().dispatchCommand( ConsoleCommandSender.getInstance(), line ) )
{
bungee.getConsole().sendMessage( ChatColor.RED + "Command not found" );
}
}
}
}
}

View File

@@ -6,29 +6,24 @@
<parent> <parent>
<groupId>net.md-5</groupId> <groupId>net.md-5</groupId>
<artifactId>bungeecord-parent</artifactId> <artifactId>bungeecord-parent</artifactId>
<version>1.6.2-SNAPSHOT</version> <version>1.6.4-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>
<groupId>net.md-5</groupId> <groupId>net.md-5</groupId>
<artifactId>bungeecord-config</artifactId> <artifactId>bungeecord-config</artifactId>
<version>1.6.2-SNAPSHOT</version> <version>1.6.4-SNAPSHOT</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>BungeeCord-Config</name> <name>BungeeCord-Config</name>
<description>Generic java configuration API intended for use with BungeeCord</description> <description>Generic java configuration API intended for use with BungeeCord</description>
<dependencies> <dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency> <dependency>
<groupId>org.yaml</groupId> <groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId> <artifactId>snakeyaml</artifactId>
<version>1.11</version> <version>1.13</version>
<scope>compile</scope>
</dependency> </dependency>
</dependencies> </dependencies>
</project> </project>

View File

@@ -2,7 +2,7 @@ package net.md_5.bungee.config;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import lombok.AccessLevel; import lombok.AccessLevel;
@@ -13,36 +13,53 @@ public final class Configuration
{ {
private static final char SEPARATOR = '.'; private static final char SEPARATOR = '.';
private final Map<String, Object> self; final Map<String, Object> self;
private Map<String, Object> comments = new HashMap<>();
private final Configuration defaults; private final Configuration defaults;
private Map<String, Object> getHolder(String path, Map<String, Object> parent, boolean create) private Configuration getSectionFor(String path)
{
return null;
}
private Object get(String path, Map<String, Object> holder)
{ {
int index = path.indexOf( SEPARATOR ); int index = path.indexOf( SEPARATOR );
String first, second;
if ( index == -1 ) if ( index == -1 )
{ {
second = path; return this;
} else
{
first = path.substring( 0, index );
second = path.substring( index + 1, path.length() );
} }
return null;
String root = path.substring( 0, index );
Object section = self.get( root );
if ( section == null )
{
section = new LinkedHashMap<>();
self.put( root, section );
}
if ( section instanceof Configuration )
{
return (Configuration) section;
}
return new Configuration( (Map) section, ( defaults == null ) ? null : defaults.getSectionFor( path ) );
}
private String getChild(String path)
{
int index = path.indexOf( SEPARATOR );
return ( index == -1 ) ? path : path.substring( index + 1 );
} }
/*------------------------------------------------------------------------*/ /*------------------------------------------------------------------------*/
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <T> T get(String path, T def) public <T> T get(String path, T def)
{ {
Object val = get( path, self ); Configuration section = getSectionFor( path );
return ( val != null && val.getClass().isInstance( def ) ) ? (T) val : (T) defaults.get( path ); Object val;
if ( section == this )
{
val = self.get( path );
} else
{
val = section.get( getChild( path ), def );
}
return ( val != null ) ? (T) val : def;
} }
public Object get(String path) public Object get(String path)
@@ -52,19 +69,26 @@ public final class Configuration
public Object getDefault(String path) public Object getDefault(String path)
{ {
return defaults.get( path ); return ( defaults == null ) ? null : defaults.get( path );
}
public void set(String path, Object value, String comment)
{
String child = path.substring( path.indexOf( SEPARATOR ) + 1 );
getHolder( path, self, true ).put( child, value );
getHolder( path, comments, true ).put( child, value );
} }
public void set(String path, Object value) public void set(String path, Object value)
{ {
set( path, value, null ); Configuration section = getSectionFor( path );
if ( section == this )
{
self.put( path, value );
} else
{
section.set( getChild( path ), value );
}
}
/*------------------------------------------------------------------------*/
public Configuration getSection(String path)
{
Object def = getDefault( path );
return new Configuration( (Map) ( get( path, ( def instanceof Map ) ? def : Collections.EMPTY_MAP ) ), ( defaults == null ) ? null : defaults.getSection( path ) );
} }
/*------------------------------------------------------------------------*/ /*------------------------------------------------------------------------*/

View File

@@ -1,7 +1,9 @@
package net.md_5.bungee.config; package net.md_5.bungee.config;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.io.Reader; import java.io.Reader;
import java.io.Writer;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@@ -15,13 +17,17 @@ public abstract class ConfigurationProvider
providers.put( YamlConfiguration.class, new YamlConfiguration() ); providers.put( YamlConfiguration.class, new YamlConfiguration() );
} }
public ConfigurationProvider getProvider(Class<? extends ConfigurationProvider> provider) public static ConfigurationProvider getProvider(Class<? extends ConfigurationProvider> provider)
{ {
return providers.get( provider ); return providers.get( provider );
} }
/*------------------------------------------------------------------------*/ /*------------------------------------------------------------------------*/
public abstract Configuration load(File file); public abstract void save(Configuration config, File file) throws IOException;
public abstract void save(Configuration config, Writer writer);
public abstract Configuration load(File file) throws IOException;
public abstract Configuration load(Reader reader); public abstract Configuration load(Reader reader);

View File

@@ -1,14 +1,18 @@
package net.md_5.bungee.config; package net.md_5.bungee.config;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader; import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import java.io.Reader; import java.io.Reader;
import java.io.Writer;
import java.util.Map; import java.util.Map;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.yaml.snakeyaml.DumperOptions; import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.Yaml; import org.yaml.snakeyaml.Yaml;
@NoArgsConstructor(access = AccessLevel.PACKAGE)
public class YamlConfiguration extends ConfigurationProvider public class YamlConfiguration extends ConfigurationProvider
{ {
@@ -24,14 +28,26 @@ public class YamlConfiguration extends ConfigurationProvider
}; };
@Override @Override
public Configuration load(File file) public void save(Configuration config, File file) throws IOException
{
try ( FileWriter writer = new FileWriter( file ) )
{
save( config, writer );
}
}
@Override
public void save(Configuration config, Writer writer)
{
yaml.get().dump( config.self, writer );
}
@Override
public Configuration load(File file) throws IOException
{ {
try ( FileReader reader = new FileReader( file ) ) try ( FileReader reader = new FileReader( file ) )
{ {
return load( reader ); return load( reader );
} catch ( IOException ex )
{
return null;
} }
} }

View File

@@ -0,0 +1,61 @@
package net.md_5.bungee.config;
import java.util.List;
import java.util.Map;
import org.junit.Assert;
import org.junit.Test;
public class YamlConfigurationTest
{
private String docuement = ""
+ "receipt: Oz-Ware Purchase Invoice\n"
+ "date: 2012-08-06\n"
+ "customer:\n"
+ " given: Dorothy\n"
+ " family: Gale\n"
+ "\n"
+ "items:\n"
+ " - part_no: A4786\n"
+ " descrip: Water Bucket (Filled)\n"
+ " price: 1.47\n"
+ " quantity: 4\n"
+ "\n"
+ " - part_no: E1628\n"
+ " descrip: High Heeled \"Ruby\" Slippers\n"
+ " size: 8\n"
+ " price: 100.27\n"
+ " quantity: 1\n"
+ "\n"
+ "bill-to: &id001\n"
+ " street: |\n"
+ " 123 Tornado Alley\n"
+ " Suite 16\n"
+ " city: East Centerville\n"
+ " state: KS\n"
+ "\n"
+ "ship-to: *id001\n"
+ "\n"
+ "specialDelivery: >\n"
+ " Follow the Yellow Brick\n"
+ " Road to the Emerald City.\n"
+ " Pay no attention to the\n"
+ " man behind the curtain.";
@Test
public void testRead() throws Exception
{
Configuration conf = ConfigurationProvider.getProvider( YamlConfiguration.class ).load( docuement );
Assert.assertEquals( "receipt", "Oz-Ware Purchase Invoice", conf.getString( "receipt" ) );
// Assert.assertEquals( "date", "2012-08-06", conf.get( "date" ).toString() );
Configuration customer = conf.getSection( "customer" );
Assert.assertEquals( "customer.given", "Dorothy", customer.getString( "given" ) );
Assert.assertEquals( "customer.given", "Dorothy", conf.getString( "customer.given" ) );
List items = conf.getList( "items" );
Map item = (Map) items.get( 0 );
Assert.assertEquals( "items[0].part_no", "A4786", item.get( "part_no" ) );
}
}

View File

@@ -6,13 +6,13 @@
<parent> <parent>
<groupId>net.md-5</groupId> <groupId>net.md-5</groupId>
<artifactId>bungeecord-parent</artifactId> <artifactId>bungeecord-parent</artifactId>
<version>1.6.2-SNAPSHOT</version> <version>1.6.4-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>
<groupId>net.md-5</groupId> <groupId>net.md-5</groupId>
<artifactId>bungeecord-event</artifactId> <artifactId>bungeecord-event</artifactId>
<version>1.6.2-SNAPSHOT</version> <version>1.6.4-SNAPSHOT</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>BungeeCord-Event</name> <name>BungeeCord-Event</name>

View File

@@ -11,7 +11,7 @@
<groupId>net.md-5</groupId> <groupId>net.md-5</groupId>
<artifactId>bungeecord-parent</artifactId> <artifactId>bungeecord-parent</artifactId>
<version>1.6.2-SNAPSHOT</version> <version>1.6.4-SNAPSHOT</version>
<packaging>pom</packaging> <packaging>pom</packaging>
<name>BungeeCord</name> <name>BungeeCord</name>
@@ -38,9 +38,12 @@
<modules> <modules>
<module>api</module> <module>api</module>
<module>bootstrap</module>
<module>config</module>
<module>event</module> <module>event</module>
<module>protocol</module> <module>protocol</module>
<module>proxy</module> <module>proxy</module>
<module>query</module>
</modules> </modules>
<scm> <scm>

View File

@@ -6,13 +6,13 @@
<parent> <parent>
<groupId>net.md-5</groupId> <groupId>net.md-5</groupId>
<artifactId>bungeecord-parent</artifactId> <artifactId>bungeecord-parent</artifactId>
<version>1.6.2-SNAPSHOT</version> <version>1.6.4-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>
<groupId>net.md-5</groupId> <groupId>net.md-5</groupId>
<artifactId>bungeecord-protocol</artifactId> <artifactId>bungeecord-protocol</artifactId>
<version>1.6.2-SNAPSHOT</version> <version>1.6.4-SNAPSHOT</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>BungeeCord-Protocol</name> <name>BungeeCord-Protocol</name>

View File

@@ -0,0 +1,10 @@
package net.md_5.bungee.protocol;
public class BadPacketException extends RuntimeException
{
public BadPacketException(String message)
{
super( message );
}
}

View File

@@ -30,8 +30,8 @@ import net.md_5.bungee.protocol.skip.PacketReader;
public class Vanilla implements Protocol public class Vanilla implements Protocol
{ {
public static final byte PROTOCOL_VERSION = 74; public static final byte PROTOCOL_VERSION = 78;
public static final String GAME_VERSION = "1.6.2"; public static final String GAME_VERSION = "1.6.4";
@Getter @Getter
private static final Vanilla instance = new Vanilla(); private static final Vanilla instance = new Vanilla();
/*========================================================================*/ /*========================================================================*/
@@ -78,7 +78,7 @@ public class Vanilla implements Protocol
DefinedPacket packet = read( packetId, buf, this ); DefinedPacket packet = read( packetId, buf, this );
if ( buf.readerIndex() == start ) if ( buf.readerIndex() == start )
{ {
throw new RuntimeException( "Unknown packet id " + packetId ); throw new BadPacketException( "Unknown packet id " + packetId );
} }
return packet; return packet;
} }
@@ -382,9 +382,5 @@ public class Vanilla implements Protocol
{ {
BYTE, FLOAT, FLOAT BYTE, FLOAT, FLOAT
}; };
opCodes[0xCB] = new OpCode[]
{
STRING
};
} }
} }

View File

@@ -1,8 +1,6 @@
package net.md_5.bungee.protocol.packet; package net.md_5.bungee.protocol.packet;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import java.util.HashMap;
import java.util.Map;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.Getter; import lombok.Getter;
import lombok.ToString; import lombok.ToString;

View File

@@ -3,15 +3,17 @@ package net.md_5.bungee.protocol.packet;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.Getter; import lombok.Getter;
import lombok.Setter;
import lombok.ToString; import lombok.ToString;
@Getter @Getter
@Setter
@ToString @ToString
@EqualsAndHashCode(callSuper = false) @EqualsAndHashCode(callSuper = false)
public class Packet2Handshake extends DefinedPacket public class Packet2Handshake extends DefinedPacket
{ {
private byte procolVersion; private byte protocolVersion;
private String username; private String username;
private String host; private String host;
private int port; private int port;
@@ -24,7 +26,7 @@ public class Packet2Handshake extends DefinedPacket
@Override @Override
public void read(ByteBuf buf) public void read(ByteBuf buf)
{ {
procolVersion = buf.readByte(); protocolVersion = buf.readByte();
username = readString( buf ); username = readString( buf );
host = readString( buf ); host = readString( buf );
port = buf.readInt(); port = buf.readInt();
@@ -33,7 +35,7 @@ public class Packet2Handshake extends DefinedPacket
@Override @Override
public void write(ByteBuf buf) public void write(ByteBuf buf)
{ {
buf.writeByte( procolVersion ); buf.writeByte( protocolVersion );
writeString( username, buf ); writeString( username, buf );
writeString( host, buf ); writeString( host, buf );
buf.writeInt( port ); buf.writeInt( port );

View File

@@ -34,18 +34,13 @@ public class PacketCBTabComplete extends DefinedPacket
@Override @Override
public void write(ByteBuf buf) public void write(ByteBuf buf)
{ {
String tab = ""; StringBuilder tab = new StringBuilder();
for ( String alternative : commands ) for ( String alternative : commands )
{ {
if ( tab.isEmpty() ) tab.append( alternative );
{ tab.append( "\00" );
tab = alternative + " ";
} else
{
tab += "\0" + alternative + " ";
} }
} writeString( tab.substring( 0, tab.length() - 1 ), buf );
writeString( tab, buf );
} }
@Override @Override

View File

@@ -6,13 +6,13 @@
<parent> <parent>
<groupId>net.md-5</groupId> <groupId>net.md-5</groupId>
<artifactId>bungeecord-parent</artifactId> <artifactId>bungeecord-parent</artifactId>
<version>1.6.2-SNAPSHOT</version> <version>1.6.4-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>
<groupId>net.md-5</groupId> <groupId>net.md-5</groupId>
<artifactId>bungeecord-proxy</artifactId> <artifactId>bungeecord-proxy</artifactId>
<version>1.6.2-SNAPSHOT</version> <version>1.6.4-SNAPSHOT</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>BungeeCord-Proxy</name> <name>BungeeCord-Proxy</name>
@@ -41,6 +41,12 @@
<version>2.11</version> <version>2.11</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-api</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency> <dependency>
<groupId>net.md-5</groupId> <groupId>net.md-5</groupId>
<artifactId>bungeecord-protocol</artifactId> <artifactId>bungeecord-protocol</artifactId>
@@ -49,7 +55,7 @@
</dependency> </dependency>
<dependency> <dependency>
<groupId>net.md-5</groupId> <groupId>net.md-5</groupId>
<artifactId>bungeecord-api</artifactId> <artifactId>bungeecord-query</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
@@ -74,7 +80,6 @@
</dependencies> </dependencies>
<build> <build>
<finalName>BungeeCord</finalName>
<resources> <resources>
<resource> <resource>
<directory>src/main/resources</directory> <directory>src/main/resources</directory>
@@ -90,45 +95,6 @@
<skip>true</skip> <skip>true</skip>
</configuration> </configuration>
</plugin> </plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<archive>
<manifestEntries>
<Main-Class>net.md_5.bungee.BungeeCord</Main-Class>
<Implementation-Version>${describe}</Implementation-Version>
<Specification-Version>${maven.build.timestamp}</Specification-Version>
</manifestEntries>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
<configuration>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>**/*.java</exclude>
<exclude>**/*.SF</exclude>
<exclude>**/*.DSA</exclude>
</excludes>
</filter>
</filters>
</configuration>
</plugin>
</plugins> </plugins>
</build> </build>
</project> </project>

View File

@@ -20,6 +20,7 @@ import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.PrintStream; import java.io.PrintStream;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.text.MessageFormat;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Calendar; import java.util.Calendar;
import java.util.Collection; import java.util.Collection;
@@ -60,6 +61,7 @@ import net.md_5.bungee.protocol.packet.DefinedPacket;
import net.md_5.bungee.protocol.packet.Packet3Chat; import net.md_5.bungee.protocol.packet.Packet3Chat;
import net.md_5.bungee.protocol.packet.PacketFAPluginMessage; import net.md_5.bungee.protocol.packet.PacketFAPluginMessage;
import net.md_5.bungee.protocol.Vanilla; import net.md_5.bungee.protocol.Vanilla;
import net.md_5.bungee.query.RemoteQuery;
import net.md_5.bungee.tab.Custom; import net.md_5.bungee.tab.Custom;
import net.md_5.bungee.util.CaseInsensitiveMap; import net.md_5.bungee.util.CaseInsensitiveMap;
import org.fusesource.jansi.AnsiConsole; import org.fusesource.jansi.AnsiConsole;
@@ -81,7 +83,7 @@ public class BungeeCord extends ProxyServer
/** /**
* Localization bundle. * Localization bundle.
*/ */
public final ResourceBundle bundle = ResourceBundle.getBundle( "messages_en" ); public final ResourceBundle bundle = ResourceBundle.getBundle( "messages" );
public final MultithreadEventLoopGroup eventLoops = new NioEventLoopGroup( 0, new ThreadFactoryBuilder().setNameFormat( "Netty IO Thread #%1$d" ).build() ); public final MultithreadEventLoopGroup eventLoops = new NioEventLoopGroup( 0, new ThreadFactoryBuilder().setNameFormat( "Netty IO Thread #%1$d" ).build() );
/** /**
* locations.yml save thread. * locations.yml save thread.
@@ -160,46 +162,6 @@ public class BungeeCord extends ProxyServer
} }
} }
/**
* Starts a new instance of BungeeCord.
*
* @param args command line arguments, currently none are used
* @throws Exception when the server cannot be started
*/
public static void main(String[] args) throws Exception
{
if ( BungeeCord.class.getPackage().getSpecificationVersion() != null )
{
Calendar deadline = Calendar.getInstance();
deadline.add( Calendar.WEEK_OF_YEAR, 2 );
if ( Calendar.getInstance().after( new SimpleDateFormat( "yyyyMMdd" ).parse( BungeeCord.class.getPackage().getSpecificationVersion() ) ) )
{
System.err.println( "*** Warning, this build is outdated ***" );
System.err.println( "*** Please download a new build from http://ci.md-5.net/job/BungeeCord ***" );
System.err.println( "*** You will get NO support regarding this build ***" );
System.err.println( "*** Server will start in 30 seconds ***" );
Thread.sleep( TimeUnit.SECONDS.toMillis( 30 ) );
}
}
BungeeCord bungee = new BungeeCord();
ProxyServer.setInstance( bungee );
bungee.getLogger().info( "Enabled BungeeCord version " + bungee.getVersion() );
bungee.start();
while ( bungee.isRunning )
{
String line = bungee.getConsoleReader().readLine( ">" );
if ( line != null )
{
if ( !bungee.getPluginManager().dispatchCommand( ConsoleCommandSender.getInstance(), line ) )
{
bungee.getConsole().sendMessage( ChatColor.RED + "Command not found" );
}
}
}
}
/** /**
* Start this proxy instance by loading the configuration, plugins and * Start this proxy instance by loading the configuration, plugins and
* starting the connect thread. * starting the connect thread.
@@ -269,6 +231,26 @@ public class BungeeCord extends ProxyServer
.group( eventLoops ) .group( eventLoops )
.localAddress( info.getHost() ) .localAddress( info.getHost() )
.bind().addListener( listener ); .bind().addListener( listener );
if ( info.isQueryEnabled() )
{
ChannelFutureListener bindListener = new ChannelFutureListener()
{
@Override
public void operationComplete(ChannelFuture future) throws Exception
{
if ( future.isSuccess() )
{
listeners.add( future.channel() );
getLogger().info( "Started query on " + future.channel().localAddress() );
} else
{
getLogger().log( Level.WARNING, "Could not bind to host " + future.channel().remoteAddress(), future.cause() );
}
}
};
new RemoteQuery( this, info ).start( new InetSocketAddress( info.getHost().getAddress(), info.getQueryPort() ), eventLoops, bindListener );
}
} }
} }
@@ -387,12 +369,12 @@ public class BungeeCord extends ProxyServer
} }
@Override @Override
public String getTranslation(String name) public String getTranslation(String name, Object... args)
{ {
String translation = "<translation '" + name + "' missing>"; String translation = "<translation '" + name + "' missing>";
try try
{ {
translation = bundle.getString( name ); translation = MessageFormat.format( bundle.getString( name ), args );
} catch ( MissingResourceException ex ) } catch ( MissingResourceException ex )
{ {
} }

View File

@@ -89,13 +89,13 @@ public class BungeeServerInfo implements ServerInfo
Preconditions.checkNotNull( channel, "channel" ); Preconditions.checkNotNull( channel, "channel" );
Preconditions.checkNotNull( data, "data" ); Preconditions.checkNotNull( data, "data" );
synchronized ( packetQueue )
{
Server server = ( players.isEmpty() ) ? null : players.iterator().next().getServer(); Server server = ( players.isEmpty() ) ? null : players.iterator().next().getServer();
if ( server != null ) if ( server != null )
{ {
server.sendData( channel, data ); server.sendData( channel, data );
} else } else
{
synchronized ( packetQueue )
{ {
packetQueue.add( new PacketFAPluginMessage( channel, data ) ); packetQueue.add( new PacketFAPluginMessage( channel, data ) );
} }

View File

@@ -1,14 +1,15 @@
package net.md_5.bungee; package net.md_5.bungee;
import gnu.trove.map.hash.TObjectLongHashMap;
import java.net.InetAddress; import java.net.InetAddress;
import java.util.HashMap;
import java.util.Map;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor @RequiredArgsConstructor
public class ConnectionThrottle public class ConnectionThrottle
{ {
private final TObjectLongHashMap<InetAddress> throttle = new TObjectLongHashMap<>(); private final Map<InetAddress, Long> throttle = new HashMap<>();
private final int throttleTime; private final int throttleTime;
public void unthrottle(InetAddress address) public void unthrottle(InetAddress address)
@@ -18,10 +19,10 @@ public class ConnectionThrottle
public boolean throttle(InetAddress address) public boolean throttle(InetAddress address)
{ {
long value = throttle.get( address ); Long value = throttle.get( address );
long currentTime = System.currentTimeMillis(); long currentTime = System.currentTimeMillis();
throttle.put( address, currentTime ); throttle.put( address, currentTime );
return value != 0 && currentTime - value < throttleTime; return value != null && currentTime - value < throttleTime;
} }
} }

View File

@@ -40,9 +40,9 @@ public class EncryptionUtil
} }
} }
public static PacketFDEncryptionRequest encryptRequest() public static PacketFDEncryptionRequest encryptRequest(boolean onlinemode)
{ {
String hash = ( BungeeCord.getInstance().config.isOnlineMode() ) ? Long.toString( random.nextLong(), 16 ) : "-"; String hash = ( onlinemode ) ? Long.toString( random.nextLong(), 16 ) : "-";
byte[] pubKey = keys.getPublic().getEncoded(); byte[] pubKey = keys.getPublic().getEncoded();
byte[] verify = new byte[ 4 ]; byte[] verify = new byte[ 4 ];
random.nextBytes( verify ); random.nextBytes( verify );

View File

@@ -171,6 +171,8 @@ public final class UserConnection implements ProxiedPlayer
public void connect(ServerInfo info, final boolean retry) public void connect(ServerInfo info, final boolean retry)
{ {
Preconditions.checkNotNull( info, "info" );
ServerConnectEvent event = new ServerConnectEvent( this, info ); ServerConnectEvent event = new ServerConnectEvent( this, info );
if ( bungee.getPluginManager().callEvent( event ).isCancelled() ) if ( bungee.getPluginManager().callEvent( event ).isCancelled() )
{ {

View File

@@ -54,12 +54,12 @@ public class Util
+ ( ( trace.length > 0 ) ? " @ " + t.getStackTrace()[0].getClassName() + ":" + t.getStackTrace()[0].getLineNumber() : "" ); + ( ( trace.length > 0 ) ? " @ " + t.getStackTrace()[0].getClassName() + ":" + t.getStackTrace()[0].getLineNumber() : "" );
} }
public static String csv(Collection<?> objects) public static String csv(Iterable<?> objects)
{ {
return format( objects, ", " ); return format( objects, ", " );
} }
public static String format(Collection<?> objects, String separators) public static String format(Iterable<?> objects, String separators)
{ {
StringBuilder ret = new StringBuilder(); StringBuilder ret = new StringBuilder();
for ( Object o : objects ) for ( Object o : objects )

View File

@@ -32,10 +32,4 @@ public class CommandFind extends PlayerCommand
} }
} }
} }
@Override
public Iterable<String> onTabComplete(CommandSender sender, String[] args)
{
return ( args.length == 0 ) ? super.onTabComplete( sender, args ) : Collections.EMPTY_LIST;
}
} }

View File

@@ -1,7 +1,6 @@
package net.md_5.bungee.command; package net.md_5.bungee.command;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import net.md_5.bungee.Util; import net.md_5.bungee.Util;
@@ -33,31 +32,16 @@ public class CommandList extends Command
continue; continue;
} }
Collection<ProxiedPlayer> serverPlayers = server.getPlayers();
StringBuilder message = new StringBuilder();
message.append( ChatColor.GREEN );
message.append( "[" );
message.append( server.getName() );
message.append( "] " );
message.append( ChatColor.YELLOW );
message.append( "(" );
message.append( serverPlayers.size() );
message.append( "): " );
message.append( ChatColor.RESET );
List<String> players = new ArrayList<>(); List<String> players = new ArrayList<>();
for ( ProxiedPlayer player : serverPlayers ) for ( ProxiedPlayer player : server.getPlayers() )
{ {
players.add( player.getDisplayName() ); players.add( player.getDisplayName() );
} }
Collections.sort( players, String.CASE_INSENSITIVE_ORDER ); Collections.sort( players, String.CASE_INSENSITIVE_ORDER );
message.append( Util.format( players, ChatColor.RESET + ", " ) ); sender.sendMessage( ProxyServer.getInstance().getTranslation( "command_list", server.getName(), server.getPlayers().size(), Util.format( players, ChatColor.RESET + ", " ) ) );
sender.sendMessage( message.toString() );
} }
sender.sendMessage( ProxyServer.getInstance().getTranslation( "total_players" ) + ProxyServer.getInstance().getOnlineCount() ); sender.sendMessage( ProxyServer.getInstance().getTranslation( "total_players", ProxyServer.getInstance().getOnlineCount() ) );
} }
} }

View File

@@ -1,6 +1,7 @@
package net.md_5.bungee.command; package net.md_5.bungee.command;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import net.md_5.bungee.api.CommandSender; import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.ProxyServer;
@@ -24,12 +25,20 @@ public abstract class PlayerCommand extends Command implements TabExecutor
@Override @Override
public Iterable<String> onTabComplete(CommandSender sender, String[] args) public Iterable<String> onTabComplete(CommandSender sender, String[] args)
{ {
return Iterables.transform( ProxyServer.getInstance().getPlayers(), new Function<ProxiedPlayer, String>() final String lastArg = ( args.length > 0 ) ? args[args.length - 1] : "";
return Iterables.transform( Iterables.filter( ProxyServer.getInstance().getPlayers(), new Predicate<ProxiedPlayer>()
{ {
@Override @Override
public String apply(ProxiedPlayer input) public boolean apply(ProxiedPlayer player)
{ {
return input.getDisplayName(); return player.getName().startsWith( lastArg );
}
} ), new Function<ProxiedPlayer, String>()
{
@Override
public String apply(ProxiedPlayer player)
{
return player.getName();
} }
} ); } );
} }

View File

@@ -215,7 +215,10 @@ public class YamlConfig implements ConfigurationAdapter
boolean setLocalAddress = get( "bind_local_address", true, val ); boolean setLocalAddress = get( "bind_local_address", true, val );
boolean pingPassthrough = get( "ping_passthrough", false, val ); boolean pingPassthrough = get( "ping_passthrough", false, val );
ListenerInfo info = new ListenerInfo( address, motd, maxPlayers, tabListSize, defaultServer, fallbackServer, forceDefault, forced, value.clazz, setLocalAddress, pingPassthrough ); boolean query = get( "query_enabled", false, val );
int queryPort = get( "query_port", 25577, val );
ListenerInfo info = new ListenerInfo( address, motd, maxPlayers, tabListSize, defaultServer, fallbackServer, forceDefault, forced, value.clazz, setLocalAddress, pingPassthrough, queryPort, query );
ret.add( info ); ret.add( info );
} }

View File

@@ -52,6 +52,7 @@ import net.md_5.bungee.protocol.packet.PacketFDEncryptionRequest;
import net.md_5.bungee.protocol.packet.PacketFEPing; import net.md_5.bungee.protocol.packet.PacketFEPing;
import net.md_5.bungee.protocol.packet.PacketFFKick; import net.md_5.bungee.protocol.packet.PacketFFKick;
import net.md_5.bungee.api.AbstractReconnectHandler; import net.md_5.bungee.api.AbstractReconnectHandler;
import net.md_5.bungee.api.event.PlayerHandshakeEvent;
@RequiredArgsConstructor @RequiredArgsConstructor
public class InitialHandler extends PacketHandler implements PendingConnection public class InitialHandler extends PacketHandler implements PendingConnection
@@ -80,6 +81,8 @@ public class InitialHandler extends PacketHandler implements PendingConnection
ch.write( packet ); ch.write( packet );
} }
}; };
@Getter
private boolean onlineMode = BungeeCord.getInstance().config.isOnlineMode();
private ScheduledFuture<?> pingFuture; private ScheduledFuture<?> pingFuture;
private InetSocketAddress vHost; private InetSocketAddress vHost;
private byte version = -1; private byte version = -1;
@@ -177,7 +180,7 @@ public class InitialHandler extends PacketHandler implements PendingConnection
{ {
respondToPing(); respondToPing();
} }
}, 500, TimeUnit.MILLISECONDS ); }, 200, TimeUnit.MILLISECONDS );
} }
@Override @Override
@@ -198,10 +201,12 @@ public class InitialHandler extends PacketHandler implements PendingConnection
this.vHost = new InetSocketAddress( handshake.getHost(), handshake.getPort() ); this.vHost = new InetSocketAddress( handshake.getHost(), handshake.getPort() );
bungee.getLogger().log( Level.INFO, "{0} has connected", this ); bungee.getLogger().log( Level.INFO, "{0} has connected", this );
if ( handshake.getProcolVersion() > Vanilla.PROTOCOL_VERSION ) bungee.getPluginManager().callEvent( new PlayerHandshakeEvent( InitialHandler.this, handshake ) );
if ( handshake.getProtocolVersion() > Vanilla.PROTOCOL_VERSION )
{ {
disconnect( bungee.getTranslation( "outdated_server" ) ); disconnect( bungee.getTranslation( "outdated_server" ) );
} else if ( handshake.getProcolVersion() < Vanilla.PROTOCOL_VERSION ) } else if ( handshake.getProtocolVersion() < Vanilla.PROTOCOL_VERSION )
{ {
disconnect( bungee.getTranslation( "outdated_client" ) ); disconnect( bungee.getTranslation( "outdated_client" ) );
} }
@@ -220,7 +225,7 @@ public class InitialHandler extends PacketHandler implements PendingConnection
} }
// If offline mode and they are already on, don't allow connect // If offline mode and they are already on, don't allow connect
if ( !BungeeCord.getInstance().config.isOnlineMode() && bungee.getPlayer( handshake.getUsername() ) != null ) if ( !isOnlineMode() && bungee.getPlayer( handshake.getUsername() ) != null )
{ {
disconnect( bungee.getTranslation( "already_connected" ) ); disconnect( bungee.getTranslation( "already_connected" ) );
return; return;
@@ -228,7 +233,8 @@ public class InitialHandler extends PacketHandler implements PendingConnection
unsafe().sendPacket( PacketConstants.I_AM_BUNGEE ); unsafe().sendPacket( PacketConstants.I_AM_BUNGEE );
unsafe().sendPacket( PacketConstants.FORGE_MOD_REQUEST ); unsafe().sendPacket( PacketConstants.FORGE_MOD_REQUEST );
unsafe().sendPacket( request = EncryptionUtil.encryptRequest() );
unsafe().sendPacket( request = EncryptionUtil.encryptRequest( this.onlineMode ) );
thisState = State.ENCRYPT; thisState = State.ENCRYPT;
} }
@@ -241,7 +247,7 @@ public class InitialHandler extends PacketHandler implements PendingConnection
Cipher decrypt = EncryptionUtil.getCipher( Cipher.DECRYPT_MODE, sharedKey ); Cipher decrypt = EncryptionUtil.getCipher( Cipher.DECRYPT_MODE, sharedKey );
ch.addBefore( PipelineUtils.PACKET_DECODE_HANDLER, PipelineUtils.DECRYPT_HANDLER, new CipherDecoder( decrypt ) ); ch.addBefore( PipelineUtils.PACKET_DECODE_HANDLER, PipelineUtils.DECRYPT_HANDLER, new CipherDecoder( decrypt ) );
if ( BungeeCord.getInstance().config.isOnlineMode() ) if ( this.onlineMode )
{ {
String encName = URLEncoder.encode( InitialHandler.this.getName(), "UTF-8" ); String encName = URLEncoder.encode( InitialHandler.this.getName(), "UTF-8" );
@@ -381,7 +387,7 @@ public class InitialHandler extends PacketHandler implements PendingConnection
@Override @Override
public byte getVersion() public byte getVersion()
{ {
return ( handshake == null ) ? version : handshake.getProcolVersion(); return ( handshake == null ) ? version : handshake.getProtocolVersion();
} }
@Override @Override
@@ -402,6 +408,12 @@ public class InitialHandler extends PacketHandler implements PendingConnection
return unsafe; return unsafe;
} }
public void setOnlineMode(boolean onlineMode)
{
Preconditions.checkState( thisState == State.HANDSHAKE, "Can only set online mode status whilst handshaking" );
this.onlineMode = onlineMode;
}
@Override @Override
public String toString() public String toString()
{ {

View File

@@ -20,7 +20,7 @@ public class PingHandler extends PacketHandler
@Override @Override
public void connected(ChannelWrapper channel) throws Exception public void connected(ChannelWrapper channel) throws Exception
{ {
// TODO: Update this to 1.6.2 style! // TODO: Update this to 1.6.4 style!
channel.write( Unpooled.wrappedBuffer( new byte[] channel.write( Unpooled.wrappedBuffer( new byte[]
{ {
(byte) 0xFE, (byte) 0x01 (byte) 0xFE, (byte) 0x01

View File

@@ -98,7 +98,7 @@ public class UpstreamBridge extends PacketHandler
if ( tabComplete.getCursor().startsWith( "/" ) ) if ( tabComplete.getCursor().startsWith( "/" ) )
{ {
List<String> results = new ArrayList<>(); List<String> results = new ArrayList<>();
bungee.getPluginManager().dispatchCommand( con, tabComplete.getCursor().substring( 1, tabComplete.getCursor().length() ), results ); bungee.getPluginManager().dispatchCommand( con, tabComplete.getCursor().substring( 1 ), results );
if ( !results.isEmpty() ) if ( !results.isEmpty() )
{ {

View File

@@ -10,6 +10,7 @@ import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.connection.CancelSendSignal; import net.md_5.bungee.connection.CancelSendSignal;
import net.md_5.bungee.connection.InitialHandler; import net.md_5.bungee.connection.InitialHandler;
import net.md_5.bungee.connection.PingHandler; import net.md_5.bungee.connection.PingHandler;
import net.md_5.bungee.protocol.BadPacketException;
/** /**
* This class is a primitive wrapper for {@link PacketHandler} instances tied to * This class is a primitive wrapper for {@link PacketHandler} instances tied to
@@ -95,6 +96,9 @@ public class HandlerBoss extends ChannelInboundHandlerAdapter
if ( cause instanceof ReadTimeoutException ) if ( cause instanceof ReadTimeoutException )
{ {
ProxyServer.getInstance().getLogger().log( Level.WARNING, handler + " - read timed out" ); ProxyServer.getInstance().getLogger().log( Level.WARNING, handler + " - read timed out" );
} else if ( cause instanceof BadPacketException )
{
ProxyServer.getInstance().getLogger().log( Level.WARNING, handler + " - bad packet ID, are mods in use!?" );
} else if ( cause instanceof IOException ) } else if ( cause instanceof IOException )
{ {
ProxyServer.getInstance().getLogger().log( Level.WARNING, handler + " - IOException: " + cause.getMessage() ); ProxyServer.getInstance().getLogger().log( Level.WARNING, handler + " - IOException: " + cause.getMessage() );

View File

@@ -30,8 +30,9 @@ public class PipelineUtils
{ {
if ( BungeeCord.getInstance().getConnectionThrottle().throttle( ( (InetSocketAddress) ch.remoteAddress() ).getAddress() ) ) if ( BungeeCord.getInstance().getConnectionThrottle().throttle( ( (InetSocketAddress) ch.remoteAddress() ).getAddress() ) )
{ {
ch.close(); // TODO: Better throttle - we can't throttle this way if we want to maintain 1.7 compat!
return; // ch.close();
// return;
} }
BASE.initChannel( ch ); BASE.initChannel( ch );

View File

@@ -46,7 +46,7 @@ public class Custom extends TabListAdapter implements CustomTabList
if ( text != null ) if ( text != null )
{ {
Preconditions.checkArgument( text.length() <= MAX_LEN, "text must be <= %s chars", MAX_LEN ); Preconditions.checkArgument( text.length() <= MAX_LEN - 2, "text must be <= %s chars", MAX_LEN - 2 );
Preconditions.checkArgument( !ChatColor.stripColor( text ).isEmpty(), "Text cannot consist entirely of colour codes" ); Preconditions.checkArgument( !ChatColor.stripColor( text ).isEmpty(), "Text cannot consist entirely of colour codes" );
text = attempt( text ); text = attempt( text );
sentStuff.add( text ); sentStuff.add( text );

View File

@@ -0,0 +1,21 @@
alert=\u00a78[\u00a74Alert\u00a78]\u00a7r
already_connected=\u00a7cYou are already connected to this server
already_connecting=\u00a7cAlready connecting to this server!
command_list=\u00a7a[{0}] \u00a7e({1}): \u00a7r{2}
connect_kick=\u00a7cKicked whilst connecting to
current_server=\u00a76You are currently connected to
fallback_kick=\u00a7cCould not connect to default server, please try again later:
fallback_lobby=\u00a7cCould not connect to target server, you have been moved to the lobby server
lost_connection=[Proxy] Lost connection to server.
mojang_fail=Error occurred while contacting login servers, are they down?
no_permission=\u00a7cYou do not have permission to execute this command!
no_server=\u00a7cThe specified server does not exist
no_server_permission=\u00a7cYou don't have permission to access this server
outdated_client=Outdated Client!
outdated_server=Outdated Server!
proxy_full=Server is full
restart=[Proxy] Proxy restarting.
server_kick=[Kicked]
server_list=\u00a76You may connect to the following servers at this time:
server_went_down=\u00a7cThe server you were previously on went down, you have been connected to the lobby
total_players=Total players online: {0}

View File

@@ -1,20 +0,0 @@
alert: \u00a78[\u00a74Alert\u00a78]\u00a7r
already_connected: \u00a7cYou are already connected to this server
already_connecting: \u00a7cAlready connecting to this server!
connect_kick: \u00a7cKicked whilst connecting to
current_server: \u00a76You are currently connected to
fallback_kick: \u00a7cCould not connect to default server, please try again later:
fallback_lobby: \u00a7cCould not connect to target server, you have been moved to the lobby server
lost_connection: [Proxy] Lost connection to server.
mojang_fail: Error occurred while contacting login servers, are they down?
no_permission: \u00a7cYou do not have permission to execute this command!
no_server: \u00a7cThe specified server does not exist
no_server_permission: \u00a7cYou don't have permission to access this server
outdated_client: Outdated Client!
outdated_server: Outdated Server!
proxy_full: Server is full
restart: [Proxy] Proxy restarting.
server_kick: [Kicked]
server_list: \u00a76You may connect to the following servers at this time:
server_went_down: \u00a7cThe server you were previously on went down, you have been connected to the lobby
total_players: Total players online:

View File

@@ -12,7 +12,13 @@ public class ThrottleTest
public void testThrottle() throws InterruptedException, UnknownHostException public void testThrottle() throws InterruptedException, UnknownHostException
{ {
ConnectionThrottle throttle = new ConnectionThrottle( 5 ); ConnectionThrottle throttle = new ConnectionThrottle( 5 );
InetAddress address = InetAddress.getLocalHost(); InetAddress address;
try {
address = InetAddress.getLocalHost();
} catch (UnknownHostException ex) {
address = InetAddress.getByName( null );
}
Assert.assertFalse( "Address should not be throttled", throttle.throttle( address ) ); Assert.assertFalse( "Address should not be throttled", throttle.throttle( address ) );
Assert.assertTrue( "Address should be throttled", throttle.throttle( address ) ); Assert.assertTrue( "Address should be throttled", throttle.throttle( address ) );

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<project-shared-configuration>
<!--
This file contains additional configuration written by modules in the NetBeans IDE.
The configuration is intended to be shared among all the users of project and
therefore it is assumed to be part of version control checkout.
Without this configuration present, some functionality in the IDE may be limited or fail altogether.
-->
<properties xmlns="http://www.netbeans.org/ns/maven-properties-data/1">
<!--
Properties that influence various parts of the IDE, especially code formatting and the like.
You can copy and paste the single properties, into the pom.xml file and the IDE will pick them up.
That way multiple projects can share the same settings (useful for formatting rules for example).
Any value defined here will override the pom.xml file value but is only applicable to the current project.
-->
<org-netbeans-modules-editor-indent.CodeStyle.usedProfile>project</org-netbeans-modules-editor-indent.CodeStyle.usedProfile>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.classDeclBracePlacement>NEW_LINE</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.classDeclBracePlacement>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.otherBracePlacement>NEW_LINE</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.otherBracePlacement>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.methodDeclBracePlacement>NEW_LINE</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.methodDeclBracePlacement>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinMethodCallParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinMethodCallParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSwitchParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSwitchParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinCatchParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinCatchParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinTryParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinTryParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSynchronizedParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSynchronizedParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinArrayInitBrackets>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinArrayInitBrackets>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinWhileParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinWhileParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinIfParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinIfParens>
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinForParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinForParens>
</properties>
</project-shared-configuration>

35
query/pom.xml Normal file
View File

@@ -0,0 +1,35 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-parent</artifactId>
<version>1.6.4-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-query</artifactId>
<version>1.6.4-SNAPSHOT</version>
<packaging>jar</packaging>
<name>BungeeCord-Query</name>
<description>Minecraft query implementation based on the BungeeCord API.</description>
<dependencies>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-transport</artifactId>
<version>${netty.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-api</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,139 @@
package net.md_5.bungee.query;
import io.netty.buffer.ByteBuf;
import io.netty.channel.AddressedEnvelope;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.socket.DatagramPacket;
import java.nio.ByteOrder;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import lombok.RequiredArgsConstructor;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.config.ListenerInfo;
import net.md_5.bungee.api.connection.ProxiedPlayer;
@RequiredArgsConstructor
public class QueryHandler extends SimpleChannelInboundHandler<DatagramPacket>
{
private final ProxyServer bungee;
private final ListenerInfo listener;
/*========================================================================*/
private final Random random = new Random();
private final Map<Integer, Long> sessions = new HashMap<>();
private void writeShort(ByteBuf buf, int s)
{
buf.order( ByteOrder.LITTLE_ENDIAN ).writeShort( s );
}
private void writeNumber(ByteBuf buf, int i)
{
writeString( buf, Integer.toString( i ) );
}
private void writeString(ByteBuf buf, String s)
{
for ( char c : s.toCharArray() )
{
buf.writeChar( c );
}
buf.writeByte( 0x00 );
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket msg) throws Exception
{
ByteBuf in = msg.content();
if ( in.readUnsignedByte() != 0xFE && in.readUnsignedByte() != 0xFD )
{
throw new IllegalStateException( "Incorrect magic!" );
}
ByteBuf out = ctx.alloc().buffer();
AddressedEnvelope response = new DatagramPacket( out, msg.sender() );
byte type = in.readByte();
int sessionId = in.readInt();
if ( type == 0x09 )
{
out.writeByte( 0x09 );
out.writeInt( sessionId );
int challengeToken = random.nextInt();
sessions.put( challengeToken, System.currentTimeMillis() );
writeNumber( out, challengeToken );
}
if ( type == 0x00 )
{
int challengeToken = out.readInt();
Long session = sessions.get( challengeToken );
if ( session == null || System.currentTimeMillis() - session > TimeUnit.SECONDS.toMillis( 30 ) )
{
throw new IllegalStateException( "No session!" );
}
out.writeByte( 0x00 );
out.writeInt( sessionId );
if ( in.readableBytes() == 0 )
{
// Short response
writeString( out, listener.getMotd() ); // MOTD
writeString( out, "SMP" ); // Game Type
writeString( out, "BungeeCord_Proxy" ); // World Name
writeNumber( out, bungee.getOnlineCount() ); // Online Count
writeNumber( out, listener.getMaxPlayers() ); // Max Players
writeShort( out, listener.getHost().getPort() ); // Port
writeString( out, listener.getHost().getHostString() ); // IP
} else if ( in.readableBytes() == 8 )
{
// Long Response
out.writeBytes( new byte[ 11 ] );
Map<String, String> data = new HashMap<>();
data.put( "hostname", listener.getMotd() );
data.put( "gametype", "SMP" );
// Start Extra Info
data.put( "game_id", "MINECRAFT" );
data.put( "version", bungee.getGameVersion() );
// data.put( "plugins","");
// End Extra Info
data.put( "map", "BungeeCord_Proxy" );
data.put( "numplayers", Integer.toString( bungee.getOnlineCount() ) );
data.put( "maxplayers", Integer.toString( listener.getMaxPlayers() ) );
data.put( "hostport", Integer.toString( listener.getHost().getPort() ) );
data.put( "hostip", listener.getHost().getHostString() );
for ( Map.Entry<String, String> entry : data.entrySet() )
{
writeString( out, entry.getKey() );
writeString( out, entry.getValue() );
}
out.writeByte( 0x00 ); // Null
// Padding
out.writeBytes( new byte[ 10 ] );
// Player List
for ( ProxiedPlayer p : bungee.getPlayers() )
{
writeString( out, p.getName() );
}
out.writeByte( 0x00 ); // Null
} else
{
// Error!
throw new IllegalStateException( "Invalid data request packet" );
}
}
ctx.writeAndFlush( response );
}
}

View File

@@ -0,0 +1,28 @@
package net.md_5.bungee.query;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.socket.nio.NioDatagramChannel;
import java.net.InetSocketAddress;
import lombok.RequiredArgsConstructor;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.config.ListenerInfo;
@RequiredArgsConstructor
public class RemoteQuery
{
private final ProxyServer bungee;
private final ListenerInfo listener;
public void start(InetSocketAddress address, EventLoopGroup eventLoop, ChannelFutureListener future)
{
new Bootstrap()
.channel( NioDatagramChannel.class )
.group( eventLoop )
.handler( new QueryHandler( bungee, listener ) )
.localAddress( address )
.bind().addListener( future );
}
}