A ton of javadocs and small fixes in preparation for rewriting bridge system and eventual release.
This commit is contained in:
parent
c6749726c5
commit
aa2710c573
@ -11,6 +11,7 @@ import java.util.Map;
|
|||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.logging.Level;
|
||||||
import static net.md_5.bungee.Logger.$;
|
import static net.md_5.bungee.Logger.$;
|
||||||
import net.md_5.bungee.command.Command;
|
import net.md_5.bungee.command.Command;
|
||||||
import net.md_5.bungee.command.CommandEnd;
|
import net.md_5.bungee.command.CommandEnd;
|
||||||
@ -20,6 +21,9 @@ import net.md_5.bungee.command.CommandServer;
|
|||||||
import net.md_5.bungee.command.ConsoleCommandSender;
|
import net.md_5.bungee.command.ConsoleCommandSender;
|
||||||
import net.md_5.bungee.plugin.JavaPluginManager;
|
import net.md_5.bungee.plugin.JavaPluginManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main BungeeCord proxy class.
|
||||||
|
*/
|
||||||
public class BungeeCord {
|
public class BungeeCord {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -69,6 +73,12 @@ public class BungeeCord {
|
|||||||
commandMap.put("server", new CommandServer());
|
commandMap.put("server", new CommandServer());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts a new instance of BungeeCord.
|
||||||
|
*
|
||||||
|
* @param args command line arguments, currently none are used
|
||||||
|
* @throws IOException when the server cannot be started
|
||||||
|
*/
|
||||||
public static void main(String[] args) throws IOException {
|
public static void main(String[] args) throws IOException {
|
||||||
instance = new BungeeCord();
|
instance = new BungeeCord();
|
||||||
$().info("Enabled BungeeCord version " + instance.version);
|
$().info("Enabled BungeeCord version " + instance.version);
|
||||||
@ -86,26 +96,38 @@ public class BungeeCord {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dispatch a command by formatting the arguments and then executing it.
|
||||||
|
*
|
||||||
|
* @param commandLine the entire command and arguments string
|
||||||
|
* @param sender which executed the command
|
||||||
|
* @return whether the command was handled or not.
|
||||||
|
*/
|
||||||
public boolean dispatchCommand(String commandLine, CommandSender sender) {
|
public boolean dispatchCommand(String commandLine, CommandSender sender) {
|
||||||
String[] split = commandLine.trim().split(" ");
|
String[] split = commandLine.trim().split(" ");
|
||||||
String commandName = split[0].toLowerCase();
|
String commandName = split[0].toLowerCase();
|
||||||
if (commandMap.containsKey(commandName)) {
|
Command command = commandMap.get(commandName);
|
||||||
|
if (command != null) {
|
||||||
String[] args = Arrays.copyOfRange(split, 1, split.length);
|
String[] args = Arrays.copyOfRange(split, 1, split.length);
|
||||||
Command c = commandMap.get(commandName);
|
|
||||||
try {
|
try {
|
||||||
c.execute(sender, args);
|
command.execute(sender, args);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
sender.sendMessage(ChatColor.RED + "An error occurred while executing this command!");
|
sender.sendMessage(ChatColor.RED + "An error occurred while executing this command!");
|
||||||
System.err.println("----------------------- [Start of command error] -----------------------");
|
$().severe("----------------------- [Start of command error] -----------------------");
|
||||||
ex.printStackTrace();
|
$().log(Level.SEVERE, "", ex);
|
||||||
System.err.println("----------------------- [End of command error] -----------------------");
|
$().severe("----------------------- [End of command error] -----------------------");
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return command != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start this proxy instance by loading the configuration, plugins and
|
||||||
|
* starting the connect thread.
|
||||||
|
*
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
public void start() throws IOException {
|
public void start() throws IOException {
|
||||||
config.load();
|
config.load();
|
||||||
isRunning = true;
|
isRunning = true;
|
||||||
@ -120,6 +142,10 @@ public class BungeeCord {
|
|||||||
$().info("Listening on " + addr);
|
$().info("Listening on " + addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroy this proxy instance cleanly by kicking all users, saving the
|
||||||
|
* configuration and closing all sockets.
|
||||||
|
*/
|
||||||
public void stop() {
|
public void stop() {
|
||||||
this.isRunning = false;
|
this.isRunning = false;
|
||||||
$().info("Disabling plugin");
|
$().info("Disabling plugin");
|
||||||
@ -151,6 +177,13 @@ public class BungeeCord {
|
|||||||
$().info("Thank you and goodbye");
|
$().info("Thank you and goodbye");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Miscellaneous method to set options on a socket based on those in the
|
||||||
|
* configuration.
|
||||||
|
*
|
||||||
|
* @param socket to set the options on
|
||||||
|
* @throws IOException when the underlying set methods thrown an exception
|
||||||
|
*/
|
||||||
public void setSocketOptions(Socket socket) throws IOException {
|
public void setSocketOptions(Socket socket) throws IOException {
|
||||||
socket.setSoTimeout(config.timeout);
|
socket.setSoTimeout(config.timeout);
|
||||||
socket.setTrafficClass(0x18);
|
socket.setTrafficClass(0x18);
|
||||||
|
@ -1,133 +1,116 @@
|
|||||||
package net.md_5.bungee;
|
package net.md_5.bungee;
|
||||||
|
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All supported color values for chat
|
* Simplistic enumeration of all supported color values for chat.
|
||||||
*/
|
*/
|
||||||
public enum ChatColor {
|
public enum ChatColor {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents black
|
* Represents black.
|
||||||
*/
|
*/
|
||||||
BLACK('0', 0x00),
|
BLACK('0'),
|
||||||
/**
|
/**
|
||||||
* Represents dark blue
|
* Represents dark blue.
|
||||||
*/
|
*/
|
||||||
DARK_BLUE('1', 0x1),
|
DARK_BLUE('1'),
|
||||||
/**
|
/**
|
||||||
* Represents dark green
|
* Represents dark green.
|
||||||
*/
|
*/
|
||||||
DARK_GREEN('2', 0x2),
|
DARK_GREEN('2'),
|
||||||
/**
|
/**
|
||||||
* Represents dark blue (aqua)
|
* Represents dark blue (aqua).
|
||||||
*/
|
*/
|
||||||
DARK_AQUA('3', 0x3),
|
DARK_AQUA('3'),
|
||||||
/**
|
/**
|
||||||
* Represents dark red
|
* Represents dark red.
|
||||||
*/
|
*/
|
||||||
DARK_RED('4', 0x4),
|
DARK_RED('4'),
|
||||||
/**
|
/**
|
||||||
* Represents dark purple
|
* Represents dark purple.
|
||||||
*/
|
*/
|
||||||
DARK_PURPLE('5', 0x5),
|
DARK_PURPLE('5'),
|
||||||
/**
|
/**
|
||||||
* Represents gold
|
* Represents gold.
|
||||||
*/
|
*/
|
||||||
GOLD('6', 0x6),
|
GOLD('6'),
|
||||||
/**
|
/**
|
||||||
* Represents gray
|
* Represents gray.
|
||||||
*/
|
*/
|
||||||
GRAY('7', 0x7),
|
GRAY('7'),
|
||||||
/**
|
/**
|
||||||
* Represents dark gray
|
* Represents dark gray.
|
||||||
*/
|
*/
|
||||||
DARK_GRAY('8', 0x8),
|
DARK_GRAY('8'),
|
||||||
/**
|
/**
|
||||||
* Represents blue
|
* Represents blue.
|
||||||
*/
|
*/
|
||||||
BLUE('9', 0x9),
|
BLUE('9'),
|
||||||
/**
|
/**
|
||||||
* Represents green
|
* Represents green.
|
||||||
*/
|
*/
|
||||||
GREEN('a', 0xA),
|
GREEN('a'),
|
||||||
/**
|
/**
|
||||||
* Represents aqua
|
* Represents aqua.
|
||||||
*/
|
*/
|
||||||
AQUA('b', 0xB),
|
AQUA('b'),
|
||||||
/**
|
/**
|
||||||
* Represents red
|
* Represents red.
|
||||||
*/
|
*/
|
||||||
RED('c', 0xC),
|
RED('c'),
|
||||||
/**
|
/**
|
||||||
* Represents light purple
|
* Represents light purple.
|
||||||
*/
|
*/
|
||||||
LIGHT_PURPLE('d', 0xD),
|
LIGHT_PURPLE('d'),
|
||||||
/**
|
/**
|
||||||
* Represents yellow
|
* Represents yellow.
|
||||||
*/
|
*/
|
||||||
YELLOW('e', 0xE),
|
YELLOW('e'),
|
||||||
/**
|
/**
|
||||||
* Represents white
|
* Represents white.
|
||||||
*/
|
*/
|
||||||
WHITE('f', 0xF),
|
WHITE('f'),
|
||||||
/**
|
/**
|
||||||
* Represents magical characters that change around randomly
|
* Represents magical characters that change around randomly.
|
||||||
*/
|
*/
|
||||||
MAGIC('k', 0x10, true),
|
MAGIC('k'),
|
||||||
/**
|
/**
|
||||||
* Makes the text bold.
|
* Makes the text bold.
|
||||||
*/
|
*/
|
||||||
BOLD('l', 0x11, true),
|
BOLD('l'),
|
||||||
/**
|
/**
|
||||||
* Makes a line appear through the text.
|
* Makes a line appear through the text.
|
||||||
*/
|
*/
|
||||||
STRIKETHROUGH('m', 0x12, true),
|
STRIKETHROUGH('m'),
|
||||||
/**
|
/**
|
||||||
* Makes the text appear underlined.
|
* Makes the text appear underlined.
|
||||||
*/
|
*/
|
||||||
UNDERLINE('n', 0x13, true),
|
UNDERLINE('n'),
|
||||||
/**
|
/**
|
||||||
* Makes the text italic.
|
* Makes the text italic.
|
||||||
*/
|
*/
|
||||||
ITALIC('o', 0x14, true),
|
ITALIC('o'),
|
||||||
/**
|
/**
|
||||||
* Resets all previous chat colors or formats.
|
* Resets all previous chat colors or formats.
|
||||||
*/
|
*/
|
||||||
RESET('r', 0x15);
|
RESET('r');
|
||||||
/**
|
/**
|
||||||
* The special character which prefixes all chat colour codes. Use this if
|
* The special character which prefixes all chat colour codes. Use this if
|
||||||
* you need to dynamically convert colour codes from your custom format.
|
* you need to dynamically convert colour codes from your custom format.
|
||||||
*/
|
*/
|
||||||
public static final char COLOR_CHAR = '\u00A7';
|
public static final char COLOR_CHAR = '\u00A7';
|
||||||
private static final Pattern STRIP_COLOR_PATTERN = Pattern.compile("(?i)" + String.valueOf(COLOR_CHAR) + "[0-9A-FK-OR]");
|
|
||||||
private final int intCode;
|
|
||||||
private final char code;
|
|
||||||
private final boolean isFormat;
|
|
||||||
private final String toString;
|
|
||||||
private final static Map<Integer, ChatColor> BY_ID = Maps.newHashMap();
|
|
||||||
private final static Map<Character, ChatColor> BY_CHAR = Maps.newHashMap();
|
|
||||||
|
|
||||||
private ChatColor(char code, int intCode) {
|
|
||||||
this(code, intCode, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private ChatColor(char code, int intCode, boolean isFormat) {
|
|
||||||
this.code = code;
|
|
||||||
this.intCode = intCode;
|
|
||||||
this.isFormat = isFormat;
|
|
||||||
this.toString = new String(new char[]{COLOR_CHAR, code});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the char value associated with this color
|
* Pattern to remove all colour codes.
|
||||||
*
|
|
||||||
* @return A char value of this color code
|
|
||||||
*/
|
*/
|
||||||
public char getChar() {
|
private static final Pattern STRIP_COLOR_PATTERN = Pattern.compile("(?i)" + String.valueOf(COLOR_CHAR) + "[0-9A-FK-OR]");
|
||||||
return code;
|
/**
|
||||||
|
* This colour's colour char prefixed by the {@link #COLOR_CHAR}.
|
||||||
|
*/
|
||||||
|
private final String toString;
|
||||||
|
|
||||||
|
private ChatColor(char code) {
|
||||||
|
this.toString = new String(new char[]{COLOR_CHAR, code});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -135,31 +118,6 @@ public enum ChatColor {
|
|||||||
return toString;
|
return toString;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if this code is a format code as opposed to a color code.
|
|
||||||
*/
|
|
||||||
public boolean isFormat() {
|
|
||||||
return isFormat;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if this code is a color code as opposed to a format code.
|
|
||||||
*/
|
|
||||||
public boolean isColor() {
|
|
||||||
return !isFormat && this != RESET;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the color represented by the specified color code
|
|
||||||
*
|
|
||||||
* @param code Code to check
|
|
||||||
* @return Associative {@link org.bukkit.ChatColor} with the given code, or
|
|
||||||
* null if it doesn't exist
|
|
||||||
*/
|
|
||||||
public static ChatColor getByChar(char code) {
|
|
||||||
return BY_CHAR.get(code);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Strips the given message of all color codes
|
* Strips the given message of all color codes
|
||||||
*
|
*
|
||||||
@ -173,64 +131,4 @@ public enum ChatColor {
|
|||||||
|
|
||||||
return STRIP_COLOR_PATTERN.matcher(input).replaceAll("");
|
return STRIP_COLOR_PATTERN.matcher(input).replaceAll("");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Translates a string using an alternate color code character into a string
|
|
||||||
* that uses the internal ChatColor.COLOR_CODE color code character. The
|
|
||||||
* alternate color code character will only be replaced if it is immediately
|
|
||||||
* followed by 0-9, A-F, or a-f.
|
|
||||||
*
|
|
||||||
* @param altColorChar The alternate color code character to replace. Ex: &
|
|
||||||
* @param textToTranslate Text containing the alternate color code
|
|
||||||
* character.
|
|
||||||
* @return Text containing the ChatColor.COLOR_CODE color code character.
|
|
||||||
*/
|
|
||||||
public static String translateAlternateColorCodes(char altColorChar, String textToTranslate) {
|
|
||||||
char[] b = textToTranslate.toCharArray();
|
|
||||||
for (int i = 0; i < b.length - 1; i++) {
|
|
||||||
if (b[i] == altColorChar && "0123456789AaBbCcDdEeFfKkLlMmNnOoRr".indexOf(b[i + 1]) > -1) {
|
|
||||||
b[i] = ChatColor.COLOR_CHAR;
|
|
||||||
b[i + 1] = Character.toLowerCase(b[i + 1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return new String(b);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the ChatColors used at the end of the given input string.
|
|
||||||
*
|
|
||||||
* @param input Input string to retrieve the colors from.
|
|
||||||
* @return Any remaining ChatColors to pass onto the next line.
|
|
||||||
*/
|
|
||||||
public static String getLastColors(String input) {
|
|
||||||
String result = "";
|
|
||||||
int length = input.length();
|
|
||||||
|
|
||||||
// Search backwards from the end as it is faster
|
|
||||||
for (int index = length - 1; index > -1; index--) {
|
|
||||||
char section = input.charAt(index);
|
|
||||||
if (section == COLOR_CHAR && index < length - 1) {
|
|
||||||
char c = input.charAt(index + 1);
|
|
||||||
ChatColor color = getByChar(c);
|
|
||||||
|
|
||||||
if (color != null) {
|
|
||||||
result = color.toString() + result;
|
|
||||||
|
|
||||||
// Once we find a color or reset we can stop searching
|
|
||||||
if (color.isColor() || color.equals(RESET)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static {
|
|
||||||
for (ChatColor color : values()) {
|
|
||||||
BY_ID.put(color.intCode, color);
|
|
||||||
BY_CHAR.put(color.code, color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,9 @@ import static net.md_5.bungee.Logger.$;
|
|||||||
import org.yaml.snakeyaml.DumperOptions;
|
import org.yaml.snakeyaml.DumperOptions;
|
||||||
import org.yaml.snakeyaml.Yaml;
|
import org.yaml.snakeyaml.Yaml;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Core configuration for the proxy.
|
||||||
|
*/
|
||||||
public class Configuration {
|
public class Configuration {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -97,6 +100,9 @@ public class Configuration {
|
|||||||
*/
|
*/
|
||||||
public int logNumLines = 1 << 14;
|
public int logNumLines = 1 << 14;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load the configuration and save default values.
|
||||||
|
*/
|
||||||
public void load() {
|
public void load() {
|
||||||
try {
|
try {
|
||||||
file.createNewFile();
|
file.createNewFile();
|
||||||
@ -172,11 +178,17 @@ public class Configuration {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getServerFor(String user, String requestedHost) {
|
/**
|
||||||
String server;
|
* Get which server a user should be connected to, taking into account their
|
||||||
if (forcedServers.containsKey(requestedHost)) {
|
* name and virtual host.
|
||||||
server = servers.get(forcedServers.get(requestedHost));
|
*
|
||||||
} else {
|
* @param user to get a server for
|
||||||
|
* @param requestedHost the host which they connected to
|
||||||
|
* @return the name of the server which they should be connected to.
|
||||||
|
*/
|
||||||
|
public String getServer(String user, String requestedHost) {
|
||||||
|
String server = forcedServers.get(requestedHost);
|
||||||
|
if (server == null) {
|
||||||
server = reconnectLocations.get(user);
|
server = reconnectLocations.get(user);
|
||||||
}
|
}
|
||||||
if (server == null) {
|
if (server == null) {
|
||||||
@ -185,20 +197,30 @@ public class Configuration {
|
|||||||
return server;
|
return server;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setHostFor(UserConnection user, String server) {
|
/**
|
||||||
|
* Save the last server which the user was on.
|
||||||
|
*
|
||||||
|
* @param user the name of the user
|
||||||
|
* @param server which they were last on
|
||||||
|
*/
|
||||||
|
public void setServer(UserConnection user, String server) {
|
||||||
reconnectLocations.put(user.username, server);
|
reconnectLocations.put(user.username, server);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the connectable address of a server defined in the configuration.
|
||||||
|
*
|
||||||
|
* @param name the friendly name of a server
|
||||||
|
* @return the usable {@link InetSocketAddress} mapped to this server
|
||||||
|
*/
|
||||||
public InetSocketAddress getServer(String name) {
|
public InetSocketAddress getServer(String name) {
|
||||||
String hostline = (name == null) ? defaultServerName : name;
|
String server = servers.get((name == null) ? defaultServerName : name);
|
||||||
String server = servers.get(hostline);
|
return (server != null) ? Util.getAddr(server) : getServer(null);
|
||||||
if (server != null) {
|
|
||||||
return Util.getAddr(server);
|
|
||||||
} else {
|
|
||||||
return getServer(null);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save the current mappings of users to servers.
|
||||||
|
*/
|
||||||
public void saveHosts() {
|
public void saveHosts() {
|
||||||
save(reconnect, reconnectLocations);
|
save(reconnect, reconnectLocations);
|
||||||
$().info("Saved reconnect locations to " + reconnect);
|
$().info("Saved reconnect locations to " + reconnect);
|
||||||
|
@ -35,6 +35,9 @@ import org.bouncycastle.crypto.params.KeyParameter;
|
|||||||
import org.bouncycastle.crypto.params.ParametersWithIV;
|
import org.bouncycastle.crypto.params.ParametersWithIV;
|
||||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class containing all encryption related methods for the proxy.
|
||||||
|
*/
|
||||||
public class EncryptionUtil {
|
public class EncryptionUtil {
|
||||||
|
|
||||||
private static final Random secure = new SecureRandom();
|
private static final Random secure = new SecureRandom();
|
||||||
@ -57,9 +60,7 @@ public class EncryptionUtil {
|
|||||||
return new PacketFDEncryptionRequest(hash, pubKey, verify);
|
return new PacketFDEncryptionRequest(hash, pubKey, verify);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SecretKey getSecret(PacketFCEncryptionResponse resp, PacketFDEncryptionRequest request) throws BadPaddingException, IllegalBlockSizeException,
|
public static SecretKey getSecret(PacketFCEncryptionResponse resp, PacketFDEncryptionRequest request) throws BadPaddingException, IllegalBlockSizeException, IllegalStateException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException {
|
||||||
IllegalStateException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException {
|
|
||||||
|
|
||||||
Cipher cipher = Cipher.getInstance("RSA");
|
Cipher cipher = Cipher.getInstance("RSA");
|
||||||
cipher.init(Cipher.DECRYPT_MODE, keys.getPrivate());
|
cipher.init(Cipher.DECRYPT_MODE, keys.getPrivate());
|
||||||
byte[] decrypted = cipher.doFinal(resp.verifyToken);
|
byte[] decrypted = cipher.doFinal(resp.verifyToken);
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
package net.md_5.bungee;
|
package net.md_5.bungee;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class to rewrite integers within packets.
|
||||||
|
*/
|
||||||
public class EntityMap {
|
public class EntityMap {
|
||||||
|
|
||||||
public final static int[][] entityIds = new int[256][];
|
public final static int[][] entityIds = new int[256][];
|
||||||
|
@ -9,6 +9,9 @@ import static net.md_5.bungee.Logger.$;
|
|||||||
import net.md_5.bungee.packet.PacketFFKick;
|
import net.md_5.bungee.packet.PacketFFKick;
|
||||||
import net.md_5.bungee.packet.PacketInputStream;
|
import net.md_5.bungee.packet.PacketInputStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class to represent a Minecraft connection.
|
||||||
|
*/
|
||||||
@EqualsAndHashCode
|
@EqualsAndHashCode
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class GenericConnection {
|
public class GenericConnection {
|
||||||
@ -18,6 +21,11 @@ public class GenericConnection {
|
|||||||
protected final OutputStream out;
|
protected final OutputStream out;
|
||||||
public String username;
|
public String username;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close the socket with the specified reason.
|
||||||
|
*
|
||||||
|
* @param reason to disconnect
|
||||||
|
*/
|
||||||
public void disconnect(String reason) {
|
public void disconnect(String reason) {
|
||||||
if (socket.isClosed()) {
|
if (socket.isClosed()) {
|
||||||
return;
|
return;
|
||||||
|
@ -9,7 +9,7 @@ import net.md_5.bungee.packet.PacketFCEncryptionResponse;
|
|||||||
import net.md_5.bungee.packet.PacketFDEncryptionRequest;
|
import net.md_5.bungee.packet.PacketFDEncryptionRequest;
|
||||||
import net.md_5.bungee.packet.PacketFFKick;
|
import net.md_5.bungee.packet.PacketFFKick;
|
||||||
import net.md_5.bungee.packet.PacketInputStream;
|
import net.md_5.bungee.packet.PacketInputStream;
|
||||||
import net.md_5.bungee.plugin.ConnectEvent;
|
import net.md_5.bungee.plugin.HandshakeEvent;
|
||||||
import org.bouncycastle.crypto.io.CipherInputStream;
|
import org.bouncycastle.crypto.io.CipherInputStream;
|
||||||
import org.bouncycastle.crypto.io.CipherOutputStream;
|
import org.bouncycastle.crypto.io.CipherOutputStream;
|
||||||
|
|
||||||
@ -34,8 +34,8 @@ public class InitialHandler implements Runnable {
|
|||||||
case 0x02:
|
case 0x02:
|
||||||
Packet2Handshake handshake = new Packet2Handshake(packet);
|
Packet2Handshake handshake = new Packet2Handshake(packet);
|
||||||
// fire connect event
|
// fire connect event
|
||||||
ConnectEvent event = new ConnectEvent(handshake.username, socket.getInetAddress());
|
HandshakeEvent event = new HandshakeEvent(handshake.username, socket.getInetAddress());
|
||||||
BungeeCord.instance.pluginManager.onConnect(event);
|
BungeeCord.instance.pluginManager.onHandshake(event);
|
||||||
if (event.isCancelled()) {
|
if (event.isCancelled()) {
|
||||||
throw new KickException(event.getCancelReason());
|
throw new KickException(event.getCancelReason());
|
||||||
}
|
}
|
||||||
@ -59,8 +59,7 @@ public class InitialHandler implements Runnable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
UserConnection userCon = new UserConnection(socket, in, out, handshake);
|
UserConnection userCon = new UserConnection(socket, in, out, handshake);
|
||||||
userCon.register();
|
userCon.connect(BungeeCord.instance.config.getServer(handshake.username, handshake.host));
|
||||||
userCon.connect(BungeeCord.instance.config.getServerFor(handshake.username, handshake.host));
|
|
||||||
break;
|
break;
|
||||||
case 0xFE:
|
case 0xFE:
|
||||||
throw new KickException(BungeeCord.instance.config.motd + ChatColor.COLOR_CHAR + BungeeCord.instance.connections.size() + ChatColor.COLOR_CHAR + BungeeCord.instance.config.maxPlayers);
|
throw new KickException(BungeeCord.instance.config.motd + ChatColor.COLOR_CHAR + BungeeCord.instance.connections.size() + ChatColor.COLOR_CHAR + BungeeCord.instance.config.maxPlayers);
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
package net.md_5.bungee;
|
package net.md_5.bungee;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exception, which when thrown will disconnect the player from the proxy with
|
||||||
|
* the specified message.
|
||||||
|
*/
|
||||||
public class KickException extends RuntimeException {
|
public class KickException extends RuntimeException {
|
||||||
|
|
||||||
public KickException(String message) {
|
public KickException(String message) {
|
||||||
|
@ -7,6 +7,9 @@ import java.net.Socket;
|
|||||||
import java.net.SocketException;
|
import java.net.SocketException;
|
||||||
import static net.md_5.bungee.Logger.$;
|
import static net.md_5.bungee.Logger.$;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thread to listen and dispatch incoming connections to the proxy.
|
||||||
|
*/
|
||||||
public class ListenThread extends Thread {
|
public class ListenThread extends Thread {
|
||||||
|
|
||||||
public final ServerSocket socket;
|
public final ServerSocket socket;
|
||||||
|
@ -9,6 +9,9 @@ import java.util.logging.Formatter;
|
|||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.LogRecord;
|
import java.util.logging.LogRecord;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logger to handle formatting and storage of the proxy's logger.
|
||||||
|
*/
|
||||||
public class Logger extends java.util.logging.Logger {
|
public class Logger extends java.util.logging.Logger {
|
||||||
|
|
||||||
private static final Formatter formatter = new ConsoleLogFormatter();
|
private static final Formatter formatter = new ConsoleLogFormatter();
|
||||||
@ -20,7 +23,7 @@ public class Logger extends java.util.logging.Logger {
|
|||||||
FileHandler handler = new FileHandler("proxy.log", BungeeCord.instance.config.logNumLines, 1, true);
|
FileHandler handler = new FileHandler("proxy.log", BungeeCord.instance.config.logNumLines, 1, true);
|
||||||
handler.setFormatter(formatter);
|
handler.setFormatter(formatter);
|
||||||
addHandler(handler);
|
addHandler(handler);
|
||||||
} catch (IOException | SecurityException ex) {
|
} catch (IOException ex) {
|
||||||
System.err.println("Could not register logger!");
|
System.err.println("Could not register logger!");
|
||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
}
|
}
|
||||||
@ -37,6 +40,11 @@ public class Logger extends java.util.logging.Logger {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the current logger instance.
|
||||||
|
*
|
||||||
|
* @return the current logger instance
|
||||||
|
*/
|
||||||
public static Logger $() {
|
public static Logger $() {
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
package net.md_5.bungee;
|
package net.md_5.bungee;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class to call the {@link Configuration#saveHosts() } method at 5 minute
|
||||||
|
* intervals.
|
||||||
|
*/
|
||||||
public class ReconnectSaveThread extends Thread {
|
public class ReconnectSaveThread extends Thread {
|
||||||
|
|
||||||
public ReconnectSaveThread() {
|
public ReconnectSaveThread() {
|
||||||
|
@ -16,6 +16,9 @@ import net.md_5.bungee.packet.PacketInputStream;
|
|||||||
import org.bouncycastle.crypto.io.CipherInputStream;
|
import org.bouncycastle.crypto.io.CipherInputStream;
|
||||||
import org.bouncycastle.crypto.io.CipherOutputStream;
|
import org.bouncycastle.crypto.io.CipherOutputStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class representing a connection from the proxy to the server; ie upstream.
|
||||||
|
*/
|
||||||
public class ServerConnection extends GenericConnection {
|
public class ServerConnection extends GenericConnection {
|
||||||
|
|
||||||
public final String name;
|
public final String name;
|
||||||
|
@ -33,14 +33,11 @@ public class UserConnection extends GenericConnection implements CommandSender {
|
|||||||
super(socket, in, out);
|
super(socket, in, out);
|
||||||
this.handshake = handshake;
|
this.handshake = handshake;
|
||||||
username = handshake.username;
|
username = handshake.username;
|
||||||
|
BungeeCord.instance.connections.put(username, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void connect(String server) {
|
public void connect(String server) {
|
||||||
InetSocketAddress addr = BungeeCord.instance.config.getServer(server);
|
InetSocketAddress addr = BungeeCord.instance.config.getServer(server);
|
||||||
if (addr.equals(curServer())) {
|
|
||||||
sendMessage(ChatColor.RED + "You are already on this server");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
connect(server, addr);
|
connect(server, addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,14 +80,6 @@ public class UserConnection extends GenericConnection implements CommandSender {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void register() {
|
|
||||||
BungeeCord.instance.connections.put(username, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
private InetSocketAddress curServer() {
|
|
||||||
return (server == null) ? null : new InetSocketAddress(server.socket.getInetAddress(), server.socket.getPort());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void destory(String reason) {
|
private void destory(String reason) {
|
||||||
if (BungeeCord.instance.isRunning) {
|
if (BungeeCord.instance.isRunning) {
|
||||||
BungeeCord.instance.connections.remove(username);
|
BungeeCord.instance.connections.remove(username);
|
||||||
@ -98,9 +87,7 @@ public class UserConnection extends GenericConnection implements CommandSender {
|
|||||||
disconnect(reason);
|
disconnect(reason);
|
||||||
if (server != null) {
|
if (server != null) {
|
||||||
server.disconnect("Quitting");
|
server.disconnect("Quitting");
|
||||||
}
|
BungeeCord.instance.config.setServer(this, server.name);
|
||||||
if (server != null) {
|
|
||||||
BungeeCord.instance.config.setHostFor(this, server.name);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,13 +2,15 @@ package net.md_5.bungee;
|
|||||||
|
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Series of utility classes to perform various operations.
|
||||||
|
*/
|
||||||
public class Util {
|
public class Util {
|
||||||
|
|
||||||
private static final int DEFAULT_PORT = 25565;
|
private static final int DEFAULT_PORT = 25565;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Basic method to transform human readable addresses into usable address
|
* Method to transform human readable addresses into usable address objects.
|
||||||
* objects.
|
|
||||||
*
|
*
|
||||||
* @param hostline in the format of 'host:port'
|
* @param hostline in the format of 'host:port'
|
||||||
* @return the constructed hostname + port.
|
* @return the constructed hostname + port.
|
||||||
@ -23,17 +25,11 @@ public class Util {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Turns a InetSocketAddress into a string that can be reconstructed later.
|
* Gets the value of the first unsigned byte of the specified array. Useful
|
||||||
|
* for getting the id of a packet array .
|
||||||
*
|
*
|
||||||
* @param address the address to serialize
|
* @param b the array to read from
|
||||||
* @return
|
* @return the unsigned value of the first byte
|
||||||
*/
|
|
||||||
public static String getAddr(InetSocketAddress address) {
|
|
||||||
return address.getAddress().getHostAddress() + ((address.getPort() != DEFAULT_PORT) ? ":" + address.getPort() : "");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the packet id of specified byte array.
|
|
||||||
*/
|
*/
|
||||||
public static int getId(byte[] b) {
|
public static int getId(byte[] b) {
|
||||||
return b[0] & 0xFF;
|
return b[0] & 0xFF;
|
||||||
@ -57,10 +53,23 @@ public class Util {
|
|||||||
return result.toString();
|
return result.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats an integer as a hex value.
|
||||||
|
*
|
||||||
|
* @param i the integer to format
|
||||||
|
* @return the hex representation of the integer
|
||||||
|
*/
|
||||||
public static String hex(int i) {
|
public static String hex(int i) {
|
||||||
return String.format("0x%02X", i);
|
return String.format("0x%02X", i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a pretty one line version of a {@link Throwable}. Useful for
|
||||||
|
* debugging.
|
||||||
|
*
|
||||||
|
* @param t the {@link Throwable} to format.
|
||||||
|
* @return a string representing information about the {@link Throwable}
|
||||||
|
*/
|
||||||
public static String exception(Throwable t) {
|
public static String exception(Throwable t) {
|
||||||
return t.getClass().getSimpleName() + " : " + t.getMessage() + " @ " + t.getStackTrace()[0].getFileName() + ":" + t.getStackTrace()[0].getLineNumber();
|
return t.getClass().getSimpleName() + " : " + t.getMessage() + " @ " + t.getStackTrace()[0].getFileName() + ":" + t.getStackTrace()[0].getLineNumber();
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
package net.md_5.bungee.command;
|
package net.md_5.bungee.command;
|
||||||
|
|
||||||
import net.md_5.bungee.ChatColor;
|
/**
|
||||||
|
* Class which represents a proxy command. The {@link #execute(net.md_5.bungee.command.CommandSender, java.lang.String[])
|
||||||
|
* } method will be called to dispatch the command.
|
||||||
|
*/
|
||||||
public abstract class Command {
|
public abstract class Command {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -12,20 +14,4 @@ public abstract class Command {
|
|||||||
* the original command.
|
* the original command.
|
||||||
*/
|
*/
|
||||||
public abstract void execute(CommandSender sender, String[] args);
|
public abstract void execute(CommandSender sender, String[] args);
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the arg count is at least the specified amount
|
|
||||||
*
|
|
||||||
* @param sender sender to send message to if unsuccessful
|
|
||||||
* @param args to check
|
|
||||||
* @param count to compare
|
|
||||||
* @return if the arguments are valid
|
|
||||||
*/
|
|
||||||
public final boolean testArgs(CommandSender sender, String[] args, int count) {
|
|
||||||
boolean valid = args.length >= count;
|
|
||||||
if (!valid) {
|
|
||||||
sender.sendMessage(ChatColor.RED + "Please review your argument count");
|
|
||||||
}
|
|
||||||
return valid;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,9 @@ package net.md_5.bungee.command;
|
|||||||
import net.md_5.bungee.BungeeCord;
|
import net.md_5.bungee.BungeeCord;
|
||||||
import net.md_5.bungee.ChatColor;
|
import net.md_5.bungee.ChatColor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command to terminate the proxy instance. May only be used by the console.
|
||||||
|
*/
|
||||||
public class CommandEnd extends Command {
|
public class CommandEnd extends Command {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -5,6 +5,9 @@ import net.md_5.bungee.BungeeCord;
|
|||||||
import net.md_5.bungee.ChatColor;
|
import net.md_5.bungee.ChatColor;
|
||||||
import net.md_5.bungee.UserConnection;
|
import net.md_5.bungee.UserConnection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command to list all players connected to the proxy.
|
||||||
|
*/
|
||||||
public class CommandList extends Command {
|
public class CommandList extends Command {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -14,7 +17,6 @@ public class CommandList extends Command {
|
|||||||
|
|
||||||
for (UserConnection con : connections) {
|
for (UserConnection con : connections) {
|
||||||
users.append(con.username);
|
users.append(con.username);
|
||||||
users.append(ChatColor.RESET.toString());
|
|
||||||
users.append(", ");
|
users.append(", ");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,6 +5,9 @@ import net.md_5.bungee.BungeeCord;
|
|||||||
import net.md_5.bungee.ChatColor;
|
import net.md_5.bungee.ChatColor;
|
||||||
import net.md_5.bungee.UserConnection;
|
import net.md_5.bungee.UserConnection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command to list and switch a player between availible servers.
|
||||||
|
*/
|
||||||
public class CommandServer extends Command {
|
public class CommandServer extends Command {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -2,6 +2,9 @@ package net.md_5.bungee.command;
|
|||||||
|
|
||||||
import net.md_5.bungee.ChatColor;
|
import net.md_5.bungee.ChatColor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command sender representing the proxy console.
|
||||||
|
*/
|
||||||
public class ConsoleCommandSender implements CommandSender {
|
public class ConsoleCommandSender implements CommandSender {
|
||||||
|
|
||||||
public static final ConsoleCommandSender instance = new ConsoleCommandSender();
|
public static final ConsoleCommandSender instance = new ConsoleCommandSender();
|
||||||
|
@ -8,6 +8,11 @@ import java.io.DataOutput;
|
|||||||
import lombok.Delegate;
|
import lombok.Delegate;
|
||||||
import net.md_5.bungee.Util;
|
import net.md_5.bungee.Util;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class represents a packet which has been given a special definition. All
|
||||||
|
* subclasses can read and write to the backing byte array which can be
|
||||||
|
* retrieved via the {@link #getPacket()} method.
|
||||||
|
*/
|
||||||
public abstract class DefinedPacket implements DataInput, DataOutput {
|
public abstract class DefinedPacket implements DataInput, DataOutput {
|
||||||
|
|
||||||
private interface Overriden {
|
private interface Overriden {
|
||||||
@ -44,6 +49,12 @@ public abstract class DefinedPacket implements DataInput, DataOutput {
|
|||||||
writeByte(id);
|
writeByte(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the bytes that make up this packet.
|
||||||
|
*
|
||||||
|
* @return the bytes which make up this packet, either the original byte
|
||||||
|
* array or the newly written one.
|
||||||
|
*/
|
||||||
public byte[] getPacket() {
|
public byte[] getPacket() {
|
||||||
return packet == null ? out.toByteArray() : packet;
|
return packet == null ? out.toByteArray() : packet;
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,10 @@ import java.io.InputStream;
|
|||||||
import net.md_5.bungee.Util;
|
import net.md_5.bungee.Util;
|
||||||
import net.minecraft.server.Packet;
|
import net.minecraft.server.Packet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A specialized input stream to parse packets using the Mojang packet
|
||||||
|
* definitions and then return them as a byte array.
|
||||||
|
*/
|
||||||
public class PacketInputStream {
|
public class PacketInputStream {
|
||||||
|
|
||||||
private final DataInputStream dataInput;
|
private final DataInputStream dataInput;
|
||||||
@ -18,6 +22,12 @@ public class PacketInputStream {
|
|||||||
dataInput = new DataInputStream(tracker);
|
dataInput = new DataInputStream(tracker);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read an entire packet from the stream and return it as a byte array.
|
||||||
|
*
|
||||||
|
* @return the read packet
|
||||||
|
* @throws IOException when the underlying input stream throws an exception
|
||||||
|
*/
|
||||||
public byte[] readPacket() throws IOException {
|
public byte[] readPacket() throws IOException {
|
||||||
tracker.out.reset();
|
tracker.out.reset();
|
||||||
int id = tracker.read();
|
int id = tracker.read();
|
||||||
@ -33,6 +43,10 @@ public class PacketInputStream {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Input stream which will wrap another stream and copy all bytes read to a
|
||||||
|
* {@link ByteArrayOutputStream}.
|
||||||
|
*/
|
||||||
private class TrackingInputStream extends InputStream {
|
private class TrackingInputStream extends InputStream {
|
||||||
|
|
||||||
private final ByteArrayOutputStream out = new ByteArrayOutputStream();
|
private final ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
|
@ -80,13 +80,25 @@ import net.minecraft.server.Packet7UseEntity;
|
|||||||
import net.minecraft.server.Packet8UpdateHealth;
|
import net.minecraft.server.Packet8UpdateHealth;
|
||||||
import net.minecraft.server.Packet9Respawn;
|
import net.minecraft.server.Packet9Respawn;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class containing instances of all Vanilla Minecraft packets.
|
||||||
|
*/
|
||||||
public class VanillaPackets {
|
public class VanillaPackets {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Array of packet instances ordered by packet id.
|
||||||
|
*/
|
||||||
public static Packet[] packets = new Packet[256];
|
public static Packet[] packets = new Packet[256];
|
||||||
|
|
||||||
private static void map(int id, Class clazz) {
|
/**
|
||||||
|
* Adds a new instance of a packet class to the array storage.
|
||||||
|
*
|
||||||
|
* @param id of the packet to add
|
||||||
|
* @param clazz class of the packet to add
|
||||||
|
*/
|
||||||
|
private static void map(int id, Class<? extends Packet> clazz) {
|
||||||
try {
|
try {
|
||||||
packets[id] = (Packet) clazz.getDeclaredConstructor().newInstance();
|
packets[id] = clazz.getDeclaredConstructor().newInstance();
|
||||||
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException ex) {
|
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException ex) {
|
||||||
$().severe("Could not register packet id " + Util.hex(id));
|
$().severe("Could not register packet id " + Util.hex(id));
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,21 @@
|
|||||||
package net.md_5.bungee.plugin;
|
package net.md_5.bungee.plugin;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An event which may be canceled and this be prevented from happening.
|
||||||
|
*/
|
||||||
public interface Cancellable {
|
public interface Cancellable {
|
||||||
|
|
||||||
public void setCancelled(boolean cancelled);
|
/**
|
||||||
|
* Sets the canceled state of this event.
|
||||||
|
*
|
||||||
|
* @param canceled whether this event is canceled or not
|
||||||
|
*/
|
||||||
|
public void setCancelled(boolean canceled);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the canceled state of this event.
|
||||||
|
*
|
||||||
|
* @return whether this event is canceled or not
|
||||||
|
*/
|
||||||
public boolean isCancelled();
|
public boolean isCancelled();
|
||||||
}
|
}
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
package net.md_5.bungee.plugin;
|
|
||||||
|
|
||||||
import java.net.InetAddress;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public class ConnectEvent implements Cancellable {
|
|
||||||
|
|
||||||
private boolean cancelled;
|
|
||||||
private String cancelReason;
|
|
||||||
private final String username;
|
|
||||||
private final InetAddress address;
|
|
||||||
}
|
|
30
src/main/java/net/md_5/bungee/plugin/HandshakeEvent.java
Normal file
30
src/main/java/net/md_5/bungee/plugin/HandshakeEvent.java
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package net.md_5.bungee.plugin;
|
||||||
|
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event called once a remote connection has begun the login procedure. This
|
||||||
|
* event is ideal for IP banning, however must be used with care in other places
|
||||||
|
* such as logging at the username has not yet been verified with Mojang.
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class HandshakeEvent implements Cancellable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Canceled state.
|
||||||
|
*/
|
||||||
|
private boolean cancelled;
|
||||||
|
/**
|
||||||
|
* Message to use when kicking if this event is canceled.
|
||||||
|
*/
|
||||||
|
private String cancelReason;
|
||||||
|
/**
|
||||||
|
* Username which the player wishes to use.
|
||||||
|
*/
|
||||||
|
private final String username;
|
||||||
|
/**
|
||||||
|
* IP address of the remote connection.
|
||||||
|
*/
|
||||||
|
private final InetAddress address;
|
||||||
|
}
|
@ -1,5 +1,8 @@
|
|||||||
package net.md_5.bungee.plugin;
|
package net.md_5.bungee.plugin;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exception thrown when a plugin could not be loaded for any reason.
|
||||||
|
*/
|
||||||
public class InvalidPluginException extends RuntimeException {
|
public class InvalidPluginException extends RuntimeException {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
@ -3,6 +3,9 @@ package net.md_5.bungee.plugin;
|
|||||||
import net.md_5.bungee.BungeeCord;
|
import net.md_5.bungee.BungeeCord;
|
||||||
import net.md_5.bungee.command.Command;
|
import net.md_5.bungee.command.Command;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class which all proxy plugins should extend.
|
||||||
|
*/
|
||||||
public abstract class JavaPlugin {
|
public abstract class JavaPlugin {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -26,13 +29,13 @@ public abstract class JavaPlugin {
|
|||||||
* Called when a user connects with their name and address. To keep things
|
* Called when a user connects with their name and address. To keep things
|
||||||
* simple this name has not been checked with minecraft.net.
|
* simple this name has not been checked with minecraft.net.
|
||||||
*/
|
*/
|
||||||
public void onConnect(ConnectEvent event) {
|
public void onHandshake(HandshakeEvent event) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register a command.
|
* Register a command for use with the proxy.
|
||||||
*/
|
*/
|
||||||
protected void registerCommand(String label, Command command) {
|
protected final void registerCommand(String label, Command command) {
|
||||||
BungeeCord.instance.commandMap.put(label, command);
|
BungeeCord.instance.commandMap.put(label, command);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,11 +12,22 @@ import java.util.zip.ZipEntry;
|
|||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import static net.md_5.bungee.Logger.$;
|
import static net.md_5.bungee.Logger.$;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Plugin manager to handle loading and saving other JavaPlugin's. This class is
|
||||||
|
* itself a plugin for ease of use.
|
||||||
|
*/
|
||||||
public class JavaPluginManager extends JavaPlugin {
|
public class JavaPluginManager extends JavaPlugin {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set of loaded plugins.
|
||||||
|
*/
|
||||||
@Getter
|
@Getter
|
||||||
private final Set<JavaPlugin> plugins = new HashSet<>();
|
private final Set<JavaPlugin> plugins = new HashSet<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load all plugins from the plugins folder. This method must only be called
|
||||||
|
* once per instance.
|
||||||
|
*/
|
||||||
public void loadPlugins() {
|
public void loadPlugins() {
|
||||||
File dir = new File("plugins");
|
File dir = new File("plugins");
|
||||||
dir.mkdir();
|
dir.mkdir();
|
||||||
@ -58,9 +69,9 @@ public class JavaPluginManager extends JavaPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onConnect(ConnectEvent event) {
|
public void onHandshake(HandshakeEvent event) {
|
||||||
for (JavaPlugin p : plugins) {
|
for (JavaPlugin p : plugins) {
|
||||||
p.onConnect(event);
|
p.onHandshake(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,10 @@ import java.lang.reflect.Field;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.yaml.snakeyaml.Yaml;
|
import org.yaml.snakeyaml.Yaml;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* File which contains information about a plugin, its authors, and how to load
|
||||||
|
* it.
|
||||||
|
*/
|
||||||
@Data
|
@Data
|
||||||
public class PluginDescription {
|
public class PluginDescription {
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user