Compare commits
32 Commits
Minecraft-
...
Minecraft-
Author | SHA1 | Date | |
---|---|---|---|
![]() |
edc5b4dc91 | ||
![]() |
220a95aece | ||
![]() |
4685099808 | ||
![]() |
6c14f40108 | ||
![]() |
b041d84063 | ||
![]() |
a9d3d9461f | ||
![]() |
3fc7064997 | ||
![]() |
80001aa1f0 | ||
![]() |
a0d94282f6 | ||
![]() |
33e11f4c44 | ||
![]() |
b541e7aa76 | ||
![]() |
dd06937a3b | ||
![]() |
891dc87b16 | ||
![]() |
8e77cb35ff | ||
![]() |
59b32a8621 | ||
![]() |
02324206e3 | ||
![]() |
73ce828e6e | ||
![]() |
79d04bec2e | ||
![]() |
cbcd874d47 | ||
![]() |
09f123ce9a | ||
![]() |
0a5f8556fe | ||
![]() |
103a509f26 | ||
![]() |
32a5271dc3 | ||
![]() |
14389eb370 | ||
![]() |
a8b6a6b4aa | ||
![]() |
8133304cce | ||
![]() |
3e8c21a485 | ||
![]() |
f12dcc72d9 | ||
![]() |
a7a32509c7 | ||
![]() |
703a393888 | ||
![]() |
3c961cd5d9 | ||
![]() |
12ee68a315 |
16
api/pom.xml
16
api/pom.xml
@@ -6,13 +6,13 @@
|
||||
<parent>
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-parent</artifactId>
|
||||
<version>1.6.2-SNAPSHOT</version>
|
||||
<version>1.6.4-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-api</artifactId>
|
||||
<version>1.6.2-SNAPSHOT</version>
|
||||
<version>1.6.4-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>BungeeCord-API</name>
|
||||
@@ -25,6 +25,12 @@
|
||||
<version>14.0.1</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-config</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-event</artifactId>
|
||||
@@ -37,11 +43,5 @@
|
||||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.yaml</groupId>
|
||||
<artifactId>snakeyaml</artifactId>
|
||||
<version>1.12</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
@@ -53,7 +53,7 @@ public abstract class ProxyServer
|
||||
*
|
||||
* @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
|
||||
|
@@ -61,4 +61,12 @@ public class ListenerInfo
|
||||
* server (force default server).
|
||||
*/
|
||||
private final boolean pingPassthrough;
|
||||
/**
|
||||
* What port to run udp query on.
|
||||
*/
|
||||
private final int queryPort;
|
||||
/**
|
||||
* Whether to enable udp query.
|
||||
*/
|
||||
private final boolean queryEnabled;
|
||||
}
|
||||
|
@@ -14,26 +14,26 @@ public interface PendingConnection extends Connection
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* @return request virtual host or null if invalid / not specified.
|
||||
*/
|
||||
public InetSocketAddress getVirtualHost();
|
||||
InetSocketAddress getVirtualHost();
|
||||
|
||||
/**
|
||||
* Get the listener that accepted this connection.
|
||||
*
|
||||
* @return the accepting listener
|
||||
*/
|
||||
public ListenerInfo getListener();
|
||||
ListenerInfo getListener();
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -2,6 +2,7 @@ package net.md_5.bungee.api.event;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NonNull;
|
||||
import lombok.ToString;
|
||||
import net.md_5.bungee.api.config.ServerInfo;
|
||||
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.
|
||||
*/
|
||||
@NonNull
|
||||
private ServerInfo target;
|
||||
/**
|
||||
* Cancelled state.
|
||||
|
31
bootstrap/nb-configuration.xml
Normal file
31
bootstrap/nb-configuration.xml
Normal 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
97
bootstrap/pom.xml
Normal 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>
|
81
bootstrap/src/main/java/net/md_5/bungee/Bootstrap.java
Normal file
81
bootstrap/src/main/java/net/md_5/bungee/Bootstrap.java
Normal 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" );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -6,29 +6,24 @@
|
||||
<parent>
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-parent</artifactId>
|
||||
<version>1.6.2-SNAPSHOT</version>
|
||||
<version>1.6.4-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-config</artifactId>
|
||||
<version>1.6.2-SNAPSHOT</version>
|
||||
<version>1.6.4-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>BungeeCord-Config</name>
|
||||
<description>Generic java configuration API intended for use with BungeeCord</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.11</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.yaml</groupId>
|
||||
<artifactId>snakeyaml</artifactId>
|
||||
<version>1.11</version>
|
||||
<version>1.13</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
@@ -2,7 +2,7 @@ package net.md_5.bungee.config;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import lombok.AccessLevel;
|
||||
@@ -13,36 +13,53 @@ public final class Configuration
|
||||
{
|
||||
|
||||
private static final char SEPARATOR = '.';
|
||||
private final Map<String, Object> self;
|
||||
private Map<String, Object> comments = new HashMap<>();
|
||||
final Map<String, Object> self;
|
||||
private final Configuration defaults;
|
||||
|
||||
private Map<String, Object> getHolder(String path, Map<String, Object> parent, boolean create)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
private Object get(String path, Map<String, Object> holder)
|
||||
private Configuration getSectionFor(String path)
|
||||
{
|
||||
int index = path.indexOf( SEPARATOR );
|
||||
String first, second;
|
||||
if ( index == -1 )
|
||||
{
|
||||
second = path;
|
||||
} else
|
||||
{
|
||||
first = path.substring( 0, index );
|
||||
second = path.substring( index + 1, path.length() );
|
||||
return this;
|
||||
}
|
||||
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")
|
||||
public <T> T get(String path, T def)
|
||||
{
|
||||
Object val = get( path, self );
|
||||
return ( val != null && val.getClass().isInstance( def ) ) ? (T) val : (T) defaults.get( path );
|
||||
Configuration section = getSectionFor( 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)
|
||||
@@ -52,19 +69,26 @@ public final class Configuration
|
||||
|
||||
public Object getDefault(String path)
|
||||
{
|
||||
return 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 );
|
||||
return ( defaults == null ) ? null : defaults.get( path );
|
||||
}
|
||||
|
||||
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 ) );
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
@@ -1,7 +1,9 @@
|
||||
package net.md_5.bungee.config;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.io.Writer;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -15,13 +17,17 @@ public abstract class ConfigurationProvider
|
||||
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 );
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
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);
|
||||
|
||||
|
@@ -1,14 +1,18 @@
|
||||
package net.md_5.bungee.config;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.io.Writer;
|
||||
import java.util.Map;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.yaml.snakeyaml.DumperOptions;
|
||||
import org.yaml.snakeyaml.Yaml;
|
||||
|
||||
@NoArgsConstructor(access = AccessLevel.PACKAGE)
|
||||
public class YamlConfiguration extends ConfigurationProvider
|
||||
{
|
||||
|
||||
@@ -24,14 +28,26 @@ public class YamlConfiguration extends ConfigurationProvider
|
||||
};
|
||||
|
||||
@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 ) )
|
||||
{
|
||||
return load( reader );
|
||||
} catch ( IOException ex )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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" ) );
|
||||
}
|
||||
}
|
@@ -6,13 +6,13 @@
|
||||
<parent>
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-parent</artifactId>
|
||||
<version>1.6.2-SNAPSHOT</version>
|
||||
<version>1.6.4-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-event</artifactId>
|
||||
<version>1.6.2-SNAPSHOT</version>
|
||||
<version>1.6.4-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>BungeeCord-Event</name>
|
||||
|
5
pom.xml
5
pom.xml
@@ -11,7 +11,7 @@
|
||||
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-parent</artifactId>
|
||||
<version>1.6.2-SNAPSHOT</version>
|
||||
<version>1.6.4-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<name>BungeeCord</name>
|
||||
@@ -38,9 +38,12 @@
|
||||
|
||||
<modules>
|
||||
<module>api</module>
|
||||
<module>bootstrap</module>
|
||||
<module>config</module>
|
||||
<module>event</module>
|
||||
<module>protocol</module>
|
||||
<module>proxy</module>
|
||||
<module>query</module>
|
||||
</modules>
|
||||
|
||||
<scm>
|
||||
|
@@ -6,13 +6,13 @@
|
||||
<parent>
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-parent</artifactId>
|
||||
<version>1.6.2-SNAPSHOT</version>
|
||||
<version>1.6.4-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-protocol</artifactId>
|
||||
<version>1.6.2-SNAPSHOT</version>
|
||||
<version>1.6.4-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>BungeeCord-Protocol</name>
|
||||
|
@@ -0,0 +1,10 @@
|
||||
package net.md_5.bungee.protocol;
|
||||
|
||||
public class BadPacketException extends RuntimeException
|
||||
{
|
||||
|
||||
public BadPacketException(String message)
|
||||
{
|
||||
super( message );
|
||||
}
|
||||
}
|
@@ -30,8 +30,8 @@ import net.md_5.bungee.protocol.skip.PacketReader;
|
||||
public class Vanilla implements Protocol
|
||||
{
|
||||
|
||||
public static final byte PROTOCOL_VERSION = 74;
|
||||
public static final String GAME_VERSION = "1.6.2";
|
||||
public static final byte PROTOCOL_VERSION = 78;
|
||||
public static final String GAME_VERSION = "1.6.4";
|
||||
@Getter
|
||||
private static final Vanilla instance = new Vanilla();
|
||||
/*========================================================================*/
|
||||
@@ -78,7 +78,7 @@ public class Vanilla implements Protocol
|
||||
DefinedPacket packet = read( packetId, buf, this );
|
||||
if ( buf.readerIndex() == start )
|
||||
{
|
||||
throw new RuntimeException( "Unknown packet id " + packetId );
|
||||
throw new BadPacketException( "Unknown packet id " + packetId );
|
||||
}
|
||||
return packet;
|
||||
}
|
||||
@@ -382,9 +382,5 @@ public class Vanilla implements Protocol
|
||||
{
|
||||
BYTE, FLOAT, FLOAT
|
||||
};
|
||||
opCodes[0xCB] = new OpCode[]
|
||||
{
|
||||
STRING
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@@ -1,8 +1,6 @@
|
||||
package net.md_5.bungee.protocol.packet;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.ToString;
|
||||
|
@@ -3,15 +3,17 @@ package net.md_5.bungee.protocol.packet;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@ToString
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class Packet2Handshake extends DefinedPacket
|
||||
{
|
||||
|
||||
private byte procolVersion;
|
||||
private byte protocolVersion;
|
||||
private String username;
|
||||
private String host;
|
||||
private int port;
|
||||
@@ -24,7 +26,7 @@ public class Packet2Handshake extends DefinedPacket
|
||||
@Override
|
||||
public void read(ByteBuf buf)
|
||||
{
|
||||
procolVersion = buf.readByte();
|
||||
protocolVersion = buf.readByte();
|
||||
username = readString( buf );
|
||||
host = readString( buf );
|
||||
port = buf.readInt();
|
||||
@@ -33,7 +35,7 @@ public class Packet2Handshake extends DefinedPacket
|
||||
@Override
|
||||
public void write(ByteBuf buf)
|
||||
{
|
||||
buf.writeByte( procolVersion );
|
||||
buf.writeByte( protocolVersion );
|
||||
writeString( username, buf );
|
||||
writeString( host, buf );
|
||||
buf.writeInt( port );
|
||||
|
@@ -34,18 +34,13 @@ public class PacketCBTabComplete extends DefinedPacket
|
||||
@Override
|
||||
public void write(ByteBuf buf)
|
||||
{
|
||||
String tab = "";
|
||||
StringBuilder tab = new StringBuilder();
|
||||
for ( String alternative : commands )
|
||||
{
|
||||
if ( tab.isEmpty() )
|
||||
{
|
||||
tab = alternative + " ";
|
||||
} else
|
||||
{
|
||||
tab += "\0" + alternative + " ";
|
||||
tab.append( alternative );
|
||||
tab.append( "\00" );
|
||||
}
|
||||
}
|
||||
writeString( tab, buf );
|
||||
writeString( tab.substring( 0, tab.length() - 1 ), buf );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -6,13 +6,13 @@
|
||||
<parent>
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-parent</artifactId>
|
||||
<version>1.6.2-SNAPSHOT</version>
|
||||
<version>1.6.4-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-proxy</artifactId>
|
||||
<version>1.6.2-SNAPSHOT</version>
|
||||
<version>1.6.4-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>BungeeCord-Proxy</name>
|
||||
@@ -41,6 +41,12 @@
|
||||
<version>2.11</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-protocol</artifactId>
|
||||
@@ -49,7 +55,7 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-api</artifactId>
|
||||
<artifactId>bungeecord-query</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
@@ -74,7 +80,6 @@
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<finalName>BungeeCord</finalName>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
@@ -90,45 +95,6 @@
|
||||
<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.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>
|
||||
</build>
|
||||
</project>
|
||||
|
@@ -20,6 +20,7 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.text.MessageFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
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.PacketFAPluginMessage;
|
||||
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.util.CaseInsensitiveMap;
|
||||
import org.fusesource.jansi.AnsiConsole;
|
||||
@@ -81,7 +83,7 @@ public class BungeeCord extends ProxyServer
|
||||
/**
|
||||
* 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() );
|
||||
/**
|
||||
* 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
|
||||
* starting the connect thread.
|
||||
@@ -269,6 +231,26 @@ public class BungeeCord extends ProxyServer
|
||||
.group( eventLoops )
|
||||
.localAddress( info.getHost() )
|
||||
.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
|
||||
public String getTranslation(String name)
|
||||
public String getTranslation(String name, Object... args)
|
||||
{
|
||||
String translation = "<translation '" + name + "' missing>";
|
||||
try
|
||||
{
|
||||
translation = bundle.getString( name );
|
||||
translation = MessageFormat.format( bundle.getString( name ), args );
|
||||
} catch ( MissingResourceException ex )
|
||||
{
|
||||
}
|
||||
|
@@ -89,13 +89,13 @@ public class BungeeServerInfo implements ServerInfo
|
||||
Preconditions.checkNotNull( channel, "channel" );
|
||||
Preconditions.checkNotNull( data, "data" );
|
||||
|
||||
synchronized ( packetQueue )
|
||||
{
|
||||
Server server = ( players.isEmpty() ) ? null : players.iterator().next().getServer();
|
||||
if ( server != null )
|
||||
{
|
||||
server.sendData( channel, data );
|
||||
} else
|
||||
{
|
||||
synchronized ( packetQueue )
|
||||
{
|
||||
packetQueue.add( new PacketFAPluginMessage( channel, data ) );
|
||||
}
|
||||
|
@@ -1,14 +1,15 @@
|
||||
package net.md_5.bungee;
|
||||
|
||||
import gnu.trove.map.hash.TObjectLongHashMap;
|
||||
import java.net.InetAddress;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class ConnectionThrottle
|
||||
{
|
||||
|
||||
private final TObjectLongHashMap<InetAddress> throttle = new TObjectLongHashMap<>();
|
||||
private final Map<InetAddress, Long> throttle = new HashMap<>();
|
||||
private final int throttleTime;
|
||||
|
||||
public void unthrottle(InetAddress address)
|
||||
@@ -18,10 +19,10 @@ public class ConnectionThrottle
|
||||
|
||||
public boolean throttle(InetAddress address)
|
||||
{
|
||||
long value = throttle.get( address );
|
||||
Long value = throttle.get( address );
|
||||
long currentTime = System.currentTimeMillis();
|
||||
|
||||
throttle.put( address, currentTime );
|
||||
return value != 0 && currentTime - value < throttleTime;
|
||||
return value != null && currentTime - value < throttleTime;
|
||||
}
|
||||
}
|
||||
|
@@ -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[] verify = new byte[ 4 ];
|
||||
random.nextBytes( verify );
|
||||
|
@@ -171,6 +171,8 @@ public final class UserConnection implements ProxiedPlayer
|
||||
|
||||
public void connect(ServerInfo info, final boolean retry)
|
||||
{
|
||||
Preconditions.checkNotNull( info, "info" );
|
||||
|
||||
ServerConnectEvent event = new ServerConnectEvent( this, info );
|
||||
if ( bungee.getPluginManager().callEvent( event ).isCancelled() )
|
||||
{
|
||||
|
@@ -54,12 +54,12 @@ public class Util
|
||||
+ ( ( 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, ", " );
|
||||
}
|
||||
|
||||
public static String format(Collection<?> objects, String separators)
|
||||
public static String format(Iterable<?> objects, String separators)
|
||||
{
|
||||
StringBuilder ret = new StringBuilder();
|
||||
for ( Object o : objects )
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
|
@@ -1,7 +1,6 @@
|
||||
package net.md_5.bungee.command;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import net.md_5.bungee.Util;
|
||||
@@ -33,31 +32,16 @@ public class CommandList extends Command
|
||||
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<>();
|
||||
for ( ProxiedPlayer player : serverPlayers )
|
||||
for ( ProxiedPlayer player : server.getPlayers() )
|
||||
{
|
||||
players.add( player.getDisplayName() );
|
||||
}
|
||||
Collections.sort( players, String.CASE_INSENSITIVE_ORDER );
|
||||
|
||||
message.append( Util.format( players, ChatColor.RESET + ", " ) );
|
||||
|
||||
sender.sendMessage( message.toString() );
|
||||
sender.sendMessage( ProxyServer.getInstance().getTranslation( "command_list", server.getName(), server.getPlayers().size(), Util.format( players, ChatColor.RESET + ", " ) ) );
|
||||
}
|
||||
|
||||
sender.sendMessage( ProxyServer.getInstance().getTranslation( "total_players" ) + ProxyServer.getInstance().getOnlineCount() );
|
||||
sender.sendMessage( ProxyServer.getInstance().getTranslation( "total_players", ProxyServer.getInstance().getOnlineCount() ) );
|
||||
}
|
||||
}
|
||||
|
@@ -1,6 +1,7 @@
|
||||
package net.md_5.bungee.command;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.Iterables;
|
||||
import net.md_5.bungee.api.CommandSender;
|
||||
import net.md_5.bungee.api.ProxyServer;
|
||||
@@ -24,12 +25,20 @@ public abstract class PlayerCommand extends Command implements TabExecutor
|
||||
@Override
|
||||
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
|
||||
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();
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
@@ -215,7 +215,10 @@ public class YamlConfig implements ConfigurationAdapter
|
||||
boolean setLocalAddress = get( "bind_local_address", true, 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 );
|
||||
}
|
||||
|
||||
|
@@ -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.PacketFFKick;
|
||||
import net.md_5.bungee.api.AbstractReconnectHandler;
|
||||
import net.md_5.bungee.api.event.PlayerHandshakeEvent;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class InitialHandler extends PacketHandler implements PendingConnection
|
||||
@@ -80,6 +81,8 @@ public class InitialHandler extends PacketHandler implements PendingConnection
|
||||
ch.write( packet );
|
||||
}
|
||||
};
|
||||
@Getter
|
||||
private boolean onlineMode = BungeeCord.getInstance().config.isOnlineMode();
|
||||
private ScheduledFuture<?> pingFuture;
|
||||
private InetSocketAddress vHost;
|
||||
private byte version = -1;
|
||||
@@ -177,7 +180,7 @@ public class InitialHandler extends PacketHandler implements PendingConnection
|
||||
{
|
||||
respondToPing();
|
||||
}
|
||||
}, 500, TimeUnit.MILLISECONDS );
|
||||
}, 200, TimeUnit.MILLISECONDS );
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -198,10 +201,12 @@ public class InitialHandler extends PacketHandler implements PendingConnection
|
||||
this.vHost = new InetSocketAddress( handshake.getHost(), handshake.getPort() );
|
||||
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" ) );
|
||||
} else if ( handshake.getProcolVersion() < Vanilla.PROTOCOL_VERSION )
|
||||
} else if ( handshake.getProtocolVersion() < Vanilla.PROTOCOL_VERSION )
|
||||
{
|
||||
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 ( !BungeeCord.getInstance().config.isOnlineMode() && bungee.getPlayer( handshake.getUsername() ) != null )
|
||||
if ( !isOnlineMode() && bungee.getPlayer( handshake.getUsername() ) != null )
|
||||
{
|
||||
disconnect( bungee.getTranslation( "already_connected" ) );
|
||||
return;
|
||||
@@ -228,7 +233,8 @@ public class InitialHandler extends PacketHandler implements PendingConnection
|
||||
|
||||
unsafe().sendPacket( PacketConstants.I_AM_BUNGEE );
|
||||
unsafe().sendPacket( PacketConstants.FORGE_MOD_REQUEST );
|
||||
unsafe().sendPacket( request = EncryptionUtil.encryptRequest() );
|
||||
|
||||
unsafe().sendPacket( request = EncryptionUtil.encryptRequest( this.onlineMode ) );
|
||||
thisState = State.ENCRYPT;
|
||||
}
|
||||
|
||||
@@ -241,7 +247,7 @@ public class InitialHandler extends PacketHandler implements PendingConnection
|
||||
Cipher decrypt = EncryptionUtil.getCipher( Cipher.DECRYPT_MODE, sharedKey );
|
||||
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" );
|
||||
|
||||
@@ -381,7 +387,7 @@ public class InitialHandler extends PacketHandler implements PendingConnection
|
||||
@Override
|
||||
public byte getVersion()
|
||||
{
|
||||
return ( handshake == null ) ? version : handshake.getProcolVersion();
|
||||
return ( handshake == null ) ? version : handshake.getProtocolVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -402,6 +408,12 @@ public class InitialHandler extends PacketHandler implements PendingConnection
|
||||
return unsafe;
|
||||
}
|
||||
|
||||
public void setOnlineMode(boolean onlineMode)
|
||||
{
|
||||
Preconditions.checkState( thisState == State.HANDSHAKE, "Can only set online mode status whilst handshaking" );
|
||||
this.onlineMode = onlineMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
|
@@ -20,7 +20,7 @@ public class PingHandler extends PacketHandler
|
||||
@Override
|
||||
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[]
|
||||
{
|
||||
(byte) 0xFE, (byte) 0x01
|
||||
|
@@ -98,7 +98,7 @@ public class UpstreamBridge extends PacketHandler
|
||||
if ( tabComplete.getCursor().startsWith( "/" ) )
|
||||
{
|
||||
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() )
|
||||
{
|
||||
|
@@ -10,6 +10,7 @@ import net.md_5.bungee.api.ProxyServer;
|
||||
import net.md_5.bungee.connection.CancelSendSignal;
|
||||
import net.md_5.bungee.connection.InitialHandler;
|
||||
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
|
||||
@@ -95,6 +96,9 @@ public class HandlerBoss extends ChannelInboundHandlerAdapter
|
||||
if ( cause instanceof ReadTimeoutException )
|
||||
{
|
||||
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 )
|
||||
{
|
||||
ProxyServer.getInstance().getLogger().log( Level.WARNING, handler + " - IOException: " + cause.getMessage() );
|
||||
|
@@ -30,8 +30,9 @@ public class PipelineUtils
|
||||
{
|
||||
if ( BungeeCord.getInstance().getConnectionThrottle().throttle( ( (InetSocketAddress) ch.remoteAddress() ).getAddress() ) )
|
||||
{
|
||||
ch.close();
|
||||
return;
|
||||
// TODO: Better throttle - we can't throttle this way if we want to maintain 1.7 compat!
|
||||
// ch.close();
|
||||
// return;
|
||||
}
|
||||
|
||||
BASE.initChannel( ch );
|
||||
|
@@ -46,7 +46,7 @@ public class Custom extends TabListAdapter implements CustomTabList
|
||||
|
||||
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" );
|
||||
text = attempt( text );
|
||||
sentStuff.add( text );
|
||||
|
21
proxy/src/main/resources/messages.properties
Normal file
21
proxy/src/main/resources/messages.properties
Normal 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}
|
@@ -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:
|
@@ -12,7 +12,13 @@ public class ThrottleTest
|
||||
public void testThrottle() throws InterruptedException, UnknownHostException
|
||||
{
|
||||
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.assertTrue( "Address should be throttled", throttle.throttle( address ) );
|
||||
|
31
query/nb-configuration.xml
Normal file
31
query/nb-configuration.xml
Normal 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
35
query/pom.xml
Normal 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>
|
139
query/src/main/java/net/md_5/bungee/query/QueryHandler.java
Normal file
139
query/src/main/java/net/md_5/bungee/query/QueryHandler.java
Normal 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 );
|
||||
}
|
||||
}
|
28
query/src/main/java/net/md_5/bungee/query/RemoteQuery.java
Normal file
28
query/src/main/java/net/md_5/bungee/query/RemoteQuery.java
Normal 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 );
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user