diff --git a/.classpath b/.classpath
new file mode 100644
index 0000000..511b8b1
--- /dev/null
+++ b/.classpath
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..61793db
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,6 @@
+#
+# https://help.github.com/articles/dealing-with-line-endings/
+#
+# These are explicitly windows files and should use crlf
+*.bat text eol=crlf
+
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..363e476
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,9 @@
+.gradle
+.settings
+build
+bin
+eaglercraftbungee/bin
+eaglercraftbungee/rundir
+epkcompiler/bin
+spigot-server/world*
+eaglercraftbungee/rundir
\ No newline at end of file
diff --git a/.project b/.project
new file mode 100644
index 0000000..1e7ca72
--- /dev/null
+++ b/.project
@@ -0,0 +1,30 @@
+
+
+ eaglercraft-unified
+ Project eaglercraft-unified created by Buildship.
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectbuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.eclipse.buildship.core.gradleprojectnature
+
+
+
+ src_minecraft
+ 2
+ S:/Misc Minecraft/minecraft html5/minecrafthtml5mcp/src_minecraft
+
+
+
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 0000000..5b0a1bd
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,81 @@
+
+buildscript {
+ repositories {
+ jcenter()
+ }
+
+ dependencies {
+ classpath 'io.github.zebalu:teavm-gradle-plugin:1.0.0'
+ }
+}
+
+apply plugin: 'java'
+apply plugin: 'eclipse'
+apply plugin: 'io.github.zebalu.teavm-gradle-plugin'
+
+sourceCompatibility = 1.7
+targetCompatibility = 1.8
+
+sourceSets {
+ main {
+ java {
+ srcDir '../minecrafthtml5mcp/src_minecraft'
+ }
+ }
+}
+
+repositories {
+ jcenter()
+}
+dependencies {
+ implementation 'org.teavm:teavm-platform:0.6.1'
+ implementation 'org.teavm:teavm-classlib:0.6.1'
+}
+
+teavm {
+
+ compileScopes = null;
+ minifying = false;
+ maxTopLevelNames = 10000;
+ properties = null;
+ debugInformationGenerated = false;
+ sourceMapsGenerated = false;
+ sourceFilesCopied = false;
+ incremental = false;
+ transformers = null;
+
+ /** Where to save the result */
+ targetDirectory = file("javascript");
+
+ /** The directory to monitor to decide if compile is up-to-date or not */
+ //sourceDirectory = [file("src/main/java"),file("../minecrafthtml5mcp/src")];
+
+ /** How to name the result file. */
+ targetFileName = "classes.js";
+
+ /** Which class holds your public static void main(Strin[] args) method */
+ mainClass = 'net.lax1dude.eaglercraft.Client';
+
+ /** This will be the name of your main method after compilation. */
+ entryPointName = 'main';
+
+ classesToPreserve = null;
+ stopOnErrors = false;
+ optimizationLevel = "FULL"; //org.teavm.vm.TeaVMOptimizationLevel.SIMPLE;
+ fastGlobalAnalysis = false;
+ targetType = "JAVASCRIPT"; //org.teavm.tooling.TeaVMTargetType.JAVASCRIPT;
+ cacheDirectory = null;
+ wasmVersion = "V_0x1"; //org.teavm.backend.wasm.render.WasmBinaryVersion.V_0x1;
+ minHeapSize = 4;
+ maxHeapSize = 128;
+ outOfProcess = false;
+ processMemory = 512;
+ longjmpSupported = true;
+ heapDump = false;
+
+ /** Add name of configurations here where to look for jarfiles. */
+ includeJarsFrom = [];
+
+ /** By default teavmc taskd epends on javaCompile task, unless this varaibale is true. */
+ skipJavaCompile = false;
+}
diff --git a/eaglercraftbungee/.classpath b/eaglercraftbungee/.classpath
new file mode 100644
index 0000000..8cdc8a4
--- /dev/null
+++ b/eaglercraftbungee/.classpath
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/eaglercraftbungee/.project b/eaglercraftbungee/.project
new file mode 100644
index 0000000..29e667a
--- /dev/null
+++ b/eaglercraftbungee/.project
@@ -0,0 +1,17 @@
+
+
+ minecrafthtml5bungee
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/eaglercraftbungee/Java-WebSocket-1.5.1-with-dependencies.jar b/eaglercraftbungee/Java-WebSocket-1.5.1-with-dependencies.jar
new file mode 100644
index 0000000..8fb33ad
Binary files /dev/null and b/eaglercraftbungee/Java-WebSocket-1.5.1-with-dependencies.jar differ
diff --git a/eaglercraftbungee/bungee-deps.jar b/eaglercraftbungee/bungee-deps.jar
new file mode 100644
index 0000000..36b6759
Binary files /dev/null and b/eaglercraftbungee/bungee-deps.jar differ
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/BungeeCord.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/BungeeCord.java
new file mode 100644
index 0000000..f22b75f
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/BungeeCord.java
@@ -0,0 +1,472 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee;
+
+import net.md_5.bungee.tab.Custom;
+import net.md_5.bungee.api.tab.CustomTabList;
+import net.md_5.bungee.protocol.packet.Packet3Chat;
+
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+
+import net.md_5.bungee.protocol.packet.PacketFAPluginMessage;
+import java.util.Collections;
+import net.md_5.bungee.api.config.ServerInfo;
+import net.md_5.bungee.api.connection.ProxiedPlayer;
+import java.util.MissingResourceException;
+import net.md_5.bungee.protocol.packet.DefinedPacket;
+import io.netty.channel.ChannelException;
+import java.util.Iterator;
+import io.netty.util.concurrent.GenericFutureListener;
+import java.net.SocketAddress;
+import io.netty.channel.EventLoopGroup;
+import io.netty.channel.ChannelHandler;
+import io.netty.util.AttributeKey;
+import net.md_5.bungee.netty.PipelineUtils;
+import io.netty.channel.socket.nio.NioServerSocketChannel;
+import io.netty.bootstrap.ServerBootstrap;
+import io.netty.util.concurrent.Future;
+import io.netty.channel.ChannelFuture;
+import io.netty.channel.ChannelFutureListener;
+import net.md_5.bungee.api.config.ListenerInfo;
+import java.util.TimerTask;
+import net.md_5.bungee.reconnect.SQLReconnectHandler;
+import net.md_5.bungee.api.ChatColor;
+import net.md_5.bungee.api.CommandSender;
+import net.md_5.bungee.command.ConsoleCommandSender;
+import java.util.concurrent.TimeUnit;
+import java.util.Calendar;
+import java.io.IOException;
+import jline.UnsupportedTerminal;
+import java.io.OutputStream;
+import net.md_5.bungee.log.LoggingOutputStream;
+import java.util.logging.Level;
+import net.md_5.bungee.log.BungeeLogger;
+import org.fusesource.jansi.AnsiConsole;
+import jline.internal.Log;
+import java.io.PrintStream;
+import com.google.common.io.ByteStreams;
+import net.md_5.bungee.command.CommandFind;
+import net.md_5.bungee.command.CommandSend;
+import net.md_5.bungee.command.CommandPerms;
+import net.md_5.bungee.command.CommandBungee;
+import net.md_5.bungee.command.CommandAlert;
+import net.md_5.bungee.command.CommandIP;
+import net.md_5.bungee.command.CommandServer;
+import net.md_5.bungee.command.CommandList;
+import net.md_5.bungee.command.CommandEnd;
+import net.md_5.bungee.api.plugin.Command;
+import net.md_5.bungee.api.plugin.Plugin;
+import net.md_5.bungee.command.CommandReload;
+import java.util.concurrent.ExecutorService;
+import net.md_5.bungee.scheduler.BungeeScheduler;
+import net.md_5.bungee.config.YamlConfig;
+import net.md_5.bungee.eaglercraft.PluginEaglerAuth;
+import net.md_5.bungee.eaglercraft.PluginEaglerSkins;
+import net.md_5.bungee.eaglercraft.WebSocketListener;
+
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import net.md_5.bungee.util.CaseInsensitiveMap;
+import java.util.HashSet;
+import io.netty.channel.nio.NioEventLoopGroup;
+import net.md_5.bungee.scheduler.BungeeThreadPool;
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
+import java.util.logging.Logger;
+import jline.console.ConsoleReader;
+import net.md_5.bungee.api.scheduler.TaskScheduler;
+import java.io.File;
+import net.md_5.bungee.api.config.ConfigurationAdapter;
+import net.md_5.bungee.api.ReconnectHandler;
+import net.md_5.bungee.api.plugin.PluginManager;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.Map;
+import io.netty.channel.Channel;
+import java.util.Collection;
+import java.util.Timer;
+import io.netty.channel.MultithreadEventLoopGroup;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.ResourceBundle;
+import net.md_5.bungee.config.Configuration;
+import net.md_5.bungee.api.ProxyServer;
+
+public class BungeeCord extends ProxyServer {
+ public volatile boolean isRunning;
+ public final Configuration config;
+ public final ResourceBundle bundle;
+ public final ScheduledThreadPoolExecutor executors;
+ public final MultithreadEventLoopGroup eventLoops;
+ private final Timer saveThread;
+ private Collection listeners;
+ private Collection wsListeners;
+ private final Map connections;
+ private final ReadWriteLock connectionLock;
+ public final PluginManager pluginManager;
+ private ReconnectHandler reconnectHandler;
+ private ConfigurationAdapter configurationAdapter;
+ private final Collection pluginChannels;
+ private final File pluginsFolder;
+ private final TaskScheduler scheduler;
+ private ConsoleReader consoleReader;
+ private final Logger logger;
+
+ public static BungeeCord getInstance() {
+ return (BungeeCord) ProxyServer.getInstance();
+ }
+
+ public BungeeCord() throws IOException {
+ this.config = new Configuration();
+ this.bundle = ResourceBundle.getBundle("messages_en");
+ this.executors = new BungeeThreadPool(new ThreadFactoryBuilder().setNameFormat("Bungee Pool Thread #%1$d").build());
+ this.eventLoops = (MultithreadEventLoopGroup) new NioEventLoopGroup(Runtime.getRuntime().availableProcessors(), new ThreadFactoryBuilder().setNameFormat("Netty IO Thread #%1$d").build());
+ this.saveThread = new Timer("Reconnect Saver");
+ this.listeners = new HashSet();
+ this.wsListeners = new HashSet();
+ this.connections = (Map) new CaseInsensitiveMap();
+ this.connectionLock = new ReentrantReadWriteLock();
+ this.pluginManager = new PluginManager(this);
+ this.configurationAdapter = new YamlConfig();
+ this.pluginChannels = new HashSet();
+ this.pluginsFolder = new File("plugins");
+ this.scheduler = new BungeeScheduler();
+ this.getPluginManager().registerCommand(null, new CommandReload());
+ this.getPluginManager().registerCommand(null, new CommandEnd());
+ this.getPluginManager().registerCommand(null, new CommandList());
+ this.getPluginManager().registerCommand(null, new CommandServer());
+ this.getPluginManager().registerCommand(null, new CommandIP());
+ this.getPluginManager().registerCommand(null, new CommandAlert());
+ this.getPluginManager().registerCommand(null, new CommandBungee());
+ this.getPluginManager().registerCommand(null, new CommandPerms());
+ this.getPluginManager().registerCommand(null, new CommandSend());
+ this.getPluginManager().registerCommand(null, new CommandFind());
+ this.registerChannel("BungeeCord");
+ Log.setOutput(new PrintStream(ByteStreams.nullOutputStream()));
+ AnsiConsole.systemInstall();
+ this.consoleReader = new ConsoleReader();
+ this.logger = new BungeeLogger(this);
+ System.setErr(new PrintStream(new LoggingOutputStream(this.logger, Level.SEVERE), true));
+ System.setOut(new PrintStream(new LoggingOutputStream(this.logger, Level.INFO), true));
+ if (this.consoleReader.getTerminal() instanceof UnsupportedTerminal) {
+ this.logger.info("Unable to initialize fancy terminal. To fix this on Windows, install the correct Microsoft Visual C++ 2008 Runtime");
+ this.logger.info("NOTE: This error is non crucial, and BungeeCord will still function correctly! Do not bug the author about it unless you are still unable to get it working");
+ }
+ }
+
+ public static void main(final String[] args) throws Exception {
+ final BungeeCord bungee = new BungeeCord();
+ ProxyServer.setInstance(bungee);
+ bungee.getLogger().info("Enabled BungeeCord version " + bungee.getVersion());
+ bungee.start();
+ while (bungee.isRunning) {
+ final String line = bungee.getConsoleReader().readLine(">");
+ if (line != null && !bungee.getPluginManager().dispatchCommand(ConsoleCommandSender.getInstance(), line)) {
+ bungee.getConsole().sendMessage(ChatColor.RED + "Command not found");
+ }
+ }
+ }
+
+ @Override
+ public void start() throws Exception {
+ this.pluginsFolder.mkdir();
+ this.config.load();
+ this.pluginManager.detectPlugins(this.pluginsFolder);
+ this.pluginManager.addInternalPlugin(new PluginEaglerSkins());
+ if(this.config.getAuthInfo().isEnabled()) this.pluginManager.addInternalPlugin(new PluginEaglerAuth());
+ if (this.reconnectHandler == null) {
+ this.reconnectHandler = new SQLReconnectHandler();
+ }
+ this.isRunning = true;
+ this.pluginManager.loadAndEnablePlugins();
+ this.startListeners();
+ this.saveThread.scheduleAtFixedRate(new TimerTask() {
+ @Override
+ public void run() {
+ BungeeCord.this.getReconnectHandler().save();
+ }
+ }, 0L, TimeUnit.MINUTES.toMillis(5L));
+ }
+
+ public void startListeners() {
+ for (final ListenerInfo info : this.config.getListeners()) {
+ InetSocketAddress sock = info.getHost();
+ if(info.isWebsocket()) {
+ int port = 0;
+ try {
+ ServerSocket s = new ServerSocket(0, 0, InetAddress.getByName("127.11.0.1"));
+ sock = new InetSocketAddress("127.11.0.1", s.getLocalPort());
+ s.close();
+ } catch(IOException e) {
+ port = (int) (System.nanoTime() % 64000L + 1025L);
+ }
+ try {
+ this.wsListeners.add(new WebSocketListener(info, sock, this));
+ BungeeCord.this.getLogger().info("Listening websockets on " + info.getHost());
+ }catch(Throwable t) {
+ BungeeCord.this.getLogger().log(Level.WARNING, "Could not bind websocket listener to host " + info.getHost(), t);
+ }
+ }
+ final InetSocketAddress sock2 = sock;
+ final ChannelFutureListener listener = (ChannelFutureListener) new ChannelFutureListener() {
+ public void operationComplete(final ChannelFuture future) throws Exception {
+ if (future.isSuccess()) {
+ BungeeCord.this.listeners.add(future.channel());
+ BungeeCord.this.getLogger().info("Listening on " + sock2);
+ } else {
+ BungeeCord.this.getLogger().log(Level.WARNING, "Could not bind to host " + sock2, future.cause());
+ }
+ }
+ };
+ ((ServerBootstrap) ((ServerBootstrap) new ServerBootstrap().channel((Class) NioServerSocketChannel.class)).childAttr((AttributeKey) PipelineUtils.LISTENER, (Object) info).childHandler((ChannelHandler) PipelineUtils.SERVER_CHILD)
+ .group((EventLoopGroup) this.eventLoops).localAddress((SocketAddress) sock)).bind().addListener((GenericFutureListener) listener);
+ }
+ }
+
+ public void stopListeners() {
+ for (final Channel listener : this.listeners) {
+ this.getLogger().log(Level.INFO, "Closing listener {0}", listener);
+ try {
+ listener.close().syncUninterruptibly();
+ } catch (ChannelException ex) {
+ this.getLogger().severe("Could not close listen thread");
+ }
+ }
+ for (final WebSocketListener listener : this.wsListeners) {
+ this.getLogger().log(Level.INFO, "Closing websocket listener {0}", listener.getAddress());
+ try {
+ listener.stop();
+ }catch (IOException e) {
+ this.getLogger().severe("Could not close listen thread");
+ e.printStackTrace();
+ } catch (InterruptedException e) {
+ this.getLogger().severe("Could not close listen thread");
+ e.printStackTrace();
+ }
+ }
+ this.listeners.clear();
+ }
+
+ @Override
+ public void stop() {
+ new Thread("Shutdown Thread") {
+ @Override
+ public void run() {
+ BungeeCord.this.isRunning = false;
+ BungeeCord.this.executors.shutdown();
+ BungeeCord.this.stopListeners();
+ BungeeCord.this.getLogger().info("Closing pending connections");
+ BungeeCord.this.connectionLock.readLock().lock();
+ try {
+ BungeeCord.this.getLogger().info("Disconnecting " + BungeeCord.this.connections.size() + " connections");
+ for (final UserConnection user : BungeeCord.this.connections.values()) {
+ user.disconnect(BungeeCord.this.getTranslation("restart"));
+ }
+ } finally {
+ BungeeCord.this.connectionLock.readLock().unlock();
+ }
+ BungeeCord.this.getLogger().info("Closing IO threads");
+ BungeeCord.this.eventLoops.shutdownGracefully();
+ try {
+ BungeeCord.this.eventLoops.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
+ } catch (InterruptedException ex) {
+ }
+ BungeeCord.this.getLogger().info("Saving reconnect locations");
+ BungeeCord.this.reconnectHandler.save();
+ BungeeCord.this.reconnectHandler.close();
+ BungeeCord.this.saveThread.cancel();
+ BungeeCord.this.getLogger().info("Disabling plugins");
+ for (final Plugin plugin : BungeeCord.this.pluginManager.getPlugins()) {
+ plugin.onDisable();
+ BungeeCord.this.getScheduler().cancel(plugin);
+ }
+ BungeeCord.this.getLogger().info("Thankyou and goodbye");
+ System.exit(0);
+ }
+ }.start();
+ }
+
+ public void broadcast(final DefinedPacket packet) {
+ this.connectionLock.readLock().lock();
+ try {
+ for (final UserConnection con : this.connections.values()) {
+ con.unsafe().sendPacket(packet);
+ }
+ } finally {
+ this.connectionLock.readLock().unlock();
+ }
+ }
+
+ @Override
+ public String getName() {
+ return "BungeeCord";
+ }
+
+ @Override
+ public String getVersion() {
+ return (BungeeCord.class.getPackage().getImplementationVersion() == null) ? "unknown" : BungeeCord.class.getPackage().getImplementationVersion();
+ }
+
+ @Override
+ public String getTranslation(final String name) {
+ String translation = "";
+ try {
+ translation = this.bundle.getString(name);
+ } catch (MissingResourceException ex) {
+ }
+ return translation;
+ }
+
+ @Override
+ public Collection getPlayers() {
+ this.connectionLock.readLock().lock();
+ try {
+ return new HashSet(this.connections.values());
+ } finally {
+ this.connectionLock.readLock().unlock();
+ }
+ }
+
+ @Override
+ public int getOnlineCount() {
+ return this.connections.size();
+ }
+
+ @Override
+ public ProxiedPlayer getPlayer(final String name) {
+ this.connectionLock.readLock().lock();
+ try {
+ return this.connections.get(name);
+ } finally {
+ this.connectionLock.readLock().unlock();
+ }
+ }
+
+ @Override
+ public Map getServers() {
+ return (Map) this.config.getServers();
+ }
+
+ @Override
+ public ServerInfo getServerInfo(final String name) {
+ return this.getServers().get(name);
+ }
+
+ @Override
+ public void registerChannel(final String channel) {
+ synchronized (this.pluginChannels) {
+ this.pluginChannels.add(channel);
+ }
+ }
+
+ @Override
+ public void unregisterChannel(final String channel) {
+ synchronized (this.pluginChannels) {
+ this.pluginChannels.remove(channel);
+ }
+ }
+
+ @Override
+ public Collection getChannels() {
+ synchronized (this.pluginChannels) {
+ return Collections.unmodifiableCollection((Collection extends String>) this.pluginChannels);
+ }
+ }
+
+ public PacketFAPluginMessage registerChannels() {
+ return new PacketFAPluginMessage("REGISTER", Util.format(this.pluginChannels, "\u0000").getBytes());
+ }
+
+ @Override
+ public byte getProtocolVersion() {
+ return 61;
+ }
+
+ @Override
+ public String getGameVersion() {
+ return "1.5.2";
+ }
+
+ @Override
+ public ServerInfo constructServerInfo(final String name, final InetSocketAddress address, final boolean restricted) {
+ return new BungeeServerInfo(name, address, restricted);
+ }
+
+ @Override
+ public CommandSender getConsole() {
+ return ConsoleCommandSender.getInstance();
+ }
+
+ @Override
+ public void broadcast(final String message) {
+ this.getConsole().sendMessage(message);
+ this.broadcast(new Packet3Chat(message));
+ }
+
+ public void addConnection(final UserConnection con) {
+ this.connectionLock.writeLock().lock();
+ try {
+ this.connections.put(con.getName(), con);
+ } finally {
+ this.connectionLock.writeLock().unlock();
+ }
+ }
+
+ public void removeConnection(final UserConnection con) {
+ this.connectionLock.writeLock().lock();
+ try {
+ this.connections.remove(con.getName());
+ } finally {
+ this.connectionLock.writeLock().unlock();
+ }
+ }
+
+ @Override
+ public CustomTabList customTabList(final ProxiedPlayer player) {
+ return new Custom(player);
+ }
+
+ @Override
+ public PluginManager getPluginManager() {
+ return this.pluginManager;
+ }
+
+ @Override
+ public ReconnectHandler getReconnectHandler() {
+ return this.reconnectHandler;
+ }
+
+ @Override
+ public void setReconnectHandler(final ReconnectHandler reconnectHandler) {
+ this.reconnectHandler = reconnectHandler;
+ }
+
+ @Override
+ public ConfigurationAdapter getConfigurationAdapter() {
+ return this.configurationAdapter;
+ }
+
+ @Override
+ public void setConfigurationAdapter(final ConfigurationAdapter configurationAdapter) {
+ this.configurationAdapter = configurationAdapter;
+ }
+
+ @Override
+ public File getPluginsFolder() {
+ return this.pluginsFolder;
+ }
+
+ @Override
+ public TaskScheduler getScheduler() {
+ return this.scheduler;
+ }
+
+ public ConsoleReader getConsoleReader() {
+ return this.consoleReader;
+ }
+
+ @Override
+ public Logger getLogger() {
+ return this.logger;
+ }
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/BungeeServerInfo.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/BungeeServerInfo.java
new file mode 100644
index 0000000..84ee4b9
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/BungeeServerInfo.java
@@ -0,0 +1,137 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee;
+
+import java.beans.ConstructorProperties;
+import java.util.LinkedList;
+import java.util.ArrayList;
+import io.netty.util.concurrent.GenericFutureListener;
+import java.net.SocketAddress;
+import io.netty.channel.ChannelOption;
+import io.netty.channel.ChannelHandler;
+import net.md_5.bungee.netty.PipelineUtils;
+import io.netty.channel.EventLoopGroup;
+import io.netty.channel.socket.nio.NioSocketChannel;
+import io.netty.bootstrap.Bootstrap;
+import io.netty.util.concurrent.Future;
+import net.md_5.bungee.netty.PacketHandler;
+import net.md_5.bungee.connection.PingHandler;
+import net.md_5.bungee.netty.HandlerBoss;
+import io.netty.channel.ChannelFuture;
+import io.netty.channel.ChannelFutureListener;
+import net.md_5.bungee.api.ServerPing;
+import net.md_5.bungee.api.Callback;
+import net.md_5.bungee.api.connection.Server;
+import net.md_5.bungee.protocol.packet.PacketFAPluginMessage;
+import java.util.Objects;
+import com.google.common.base.Preconditions;
+import net.md_5.bungee.api.CommandSender;
+import java.util.Collections;
+import net.md_5.bungee.protocol.packet.DefinedPacket;
+import java.util.Queue;
+import net.md_5.bungee.api.connection.ProxiedPlayer;
+import java.util.Collection;
+import java.net.InetSocketAddress;
+import net.md_5.bungee.api.config.ServerInfo;
+
+public class BungeeServerInfo implements ServerInfo {
+ private final String name;
+ private final InetSocketAddress address;
+ private final Collection players;
+ private final boolean restricted;
+ private final Queue packetQueue;
+
+ public void addPlayer(final ProxiedPlayer player) {
+ synchronized (this.players) {
+ this.players.add(player);
+ }
+ }
+
+ public void removePlayer(final ProxiedPlayer player) {
+ synchronized (this.players) {
+ this.players.remove(player);
+ }
+ }
+
+ @Override
+ public Collection getPlayers() {
+ synchronized (this.players) {
+ return Collections.unmodifiableCollection((Collection extends ProxiedPlayer>) this.players);
+ }
+ }
+
+ @Override
+ public boolean canAccess(final CommandSender player) {
+ Preconditions.checkNotNull((Object) player, (Object) "player");
+ return !this.restricted || player.hasPermission("bungeecord.server." + this.name);
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ return obj instanceof ServerInfo && Objects.equals(this.getAddress(), ((ServerInfo) obj).getAddress());
+ }
+
+ @Override
+ public int hashCode() {
+ return this.address.hashCode();
+ }
+
+ @Override
+ public void sendData(final String channel, final byte[] data) {
+ Preconditions.checkNotNull((Object) channel, (Object) "channel");
+ Preconditions.checkNotNull((Object) data, (Object) "data");
+ final Server server = this.players.isEmpty() ? null : this.players.iterator().next().getServer();
+ if (server != null) {
+ server.sendData(channel, data);
+ } else {
+ synchronized (this.packetQueue) {
+ this.packetQueue.add(new PacketFAPluginMessage(channel, data));
+ }
+ }
+ }
+
+ @Override
+ public void ping(final Callback callback) {
+ Preconditions.checkNotNull((Object) callback, (Object) "callback");
+ final ChannelFutureListener listener = (ChannelFutureListener) new ChannelFutureListener() {
+ public void operationComplete(final ChannelFuture future) throws Exception {
+ if (future.isSuccess()) {
+ ((HandlerBoss) future.channel().pipeline().get((Class) HandlerBoss.class)).setHandler(new PingHandler(BungeeServerInfo.this, callback));
+ } else {
+ callback.done(null, future.cause());
+ }
+ }
+ };
+ ((Bootstrap) ((Bootstrap) ((Bootstrap) ((Bootstrap) new Bootstrap().channel((Class) NioSocketChannel.class)).group((EventLoopGroup) BungeeCord.getInstance().eventLoops)).handler((ChannelHandler) PipelineUtils.BASE))
+ .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, Integer.valueOf(5000))).remoteAddress((SocketAddress) this.getAddress()).connect().addListener((GenericFutureListener) listener);
+ }
+
+ @ConstructorProperties({ "name", "address", "restricted" })
+ public BungeeServerInfo(final String name, final InetSocketAddress address, final boolean restricted) {
+ this.players = new ArrayList();
+ this.packetQueue = new LinkedList();
+ this.name = name;
+ this.address = address;
+ this.restricted = restricted;
+ }
+
+ @Override
+ public String getName() {
+ return this.name;
+ }
+
+ @Override
+ public InetSocketAddress getAddress() {
+ return this.address;
+ }
+
+ public boolean isRestricted() {
+ return this.restricted;
+ }
+
+ public Queue getPacketQueue() {
+ return this.packetQueue;
+ }
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/EncryptionUtil.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/EncryptionUtil.java
new file mode 100644
index 0000000..3f0ade9
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/EncryptionUtil.java
@@ -0,0 +1,79 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee;
+
+import java.security.NoSuchAlgorithmException;
+import java.security.KeyPairGenerator;
+import java.security.spec.X509EncodedKeySpec;
+import java.security.KeyFactory;
+import java.security.PublicKey;
+import javax.crypto.spec.IvParameterSpec;
+import java.security.GeneralSecurityException;
+import javax.crypto.spec.SecretKeySpec;
+import java.util.Arrays;
+import java.security.Key;
+import javax.crypto.Cipher;
+import net.md_5.bungee.protocol.packet.PacketFCEncryptionResponse;
+import net.md_5.bungee.protocol.packet.PacketFDEncryptionRequest;
+import javax.crypto.SecretKey;
+import java.security.KeyPair;
+import java.util.Random;
+
+public class EncryptionUtil
+{
+ private static final Random random;
+ public static KeyPair keys;
+ private static SecretKey secret;
+
+ public static PacketFDEncryptionRequest encryptRequest() {
+ final String hash = BungeeCord.getInstance().config.isOnlineMode() ? Long.toString(EncryptionUtil.random.nextLong(), 16) : "-";
+ final byte[] pubKey = EncryptionUtil.keys.getPublic().getEncoded();
+ final byte[] verify = new byte[4];
+ EncryptionUtil.random.nextBytes(verify);
+ return new PacketFDEncryptionRequest(hash, pubKey, verify);
+ }
+
+ public static SecretKey getSecret(final PacketFCEncryptionResponse resp, final PacketFDEncryptionRequest request) throws GeneralSecurityException {
+ final Cipher cipher = Cipher.getInstance("RSA");
+ cipher.init(2, EncryptionUtil.keys.getPrivate());
+ final byte[] decrypted = cipher.doFinal(resp.getVerifyToken());
+ if (!Arrays.equals(request.getVerifyToken(), decrypted)) {
+ throw new IllegalStateException("Key pairs do not match!");
+ }
+ cipher.init(2, EncryptionUtil.keys.getPrivate());
+ return new SecretKeySpec(cipher.doFinal(resp.getSharedSecret()), "AES");
+ }
+
+ public static Cipher getCipher(final int opMode, final Key shared) throws GeneralSecurityException {
+ final Cipher cip = Cipher.getInstance("AES/CFB8/NoPadding");
+ cip.init(opMode, shared, new IvParameterSpec(shared.getEncoded()));
+ return cip;
+ }
+
+ public static PublicKey getPubkey(final PacketFDEncryptionRequest request) throws GeneralSecurityException {
+ return KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(request.getPublicKey()));
+ }
+
+ public static byte[] encrypt(final Key key, final byte[] b) throws GeneralSecurityException {
+ final Cipher hasher = Cipher.getInstance("RSA");
+ hasher.init(1, key);
+ return hasher.doFinal(b);
+ }
+
+ public static SecretKey getSecret() {
+ return EncryptionUtil.secret;
+ }
+
+ static {
+ random = new Random();
+ EncryptionUtil.secret = new SecretKeySpec(new byte[16], "AES");
+ try {
+ EncryptionUtil.keys = KeyPairGenerator.getInstance("RSA").generateKeyPair();
+ }
+ catch (NoSuchAlgorithmException ex) {
+ throw new ExceptionInInitializerError(ex);
+ }
+ }
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/EntityMap.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/EntityMap.java
new file mode 100644
index 0000000..45c0682
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/EntityMap.java
@@ -0,0 +1,83 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee;
+
+public class EntityMap {
+ public static final int[][] entityIds;
+
+ public static void rewrite(final byte[] packet, final int oldId, final int newId) {
+ final int packetId = packet[0] & 0xFF;
+ if (packetId == 29) {
+ for (int pos = 2; pos < packet.length; pos += 4) {
+ final int readId = readInt(packet, pos);
+ if (readId == oldId) {
+ setInt(packet, pos, newId);
+ } else if (readId == newId) {
+ setInt(packet, pos, oldId);
+ }
+ }
+ } else {
+ final int[] idArray = EntityMap.entityIds[packetId];
+ if (idArray != null) {
+ for (final int pos2 : idArray) {
+ final int readId2 = readInt(packet, pos2);
+ if (readId2 == oldId) {
+ setInt(packet, pos2, newId);
+ } else if (readId2 == newId) {
+ setInt(packet, pos2, oldId);
+ }
+ }
+ }
+ }
+ if (packetId == 23) {
+ final int type = packet[5] & 0xFF;
+ if (type == 60 || type == 90) {
+ final int index20 = readInt(packet, 20);
+ if (packet.length > 24 && index20 == oldId) {
+ setInt(packet, 20, newId);
+ }
+ }
+ }
+ }
+
+ private static void setInt(final byte[] buf, final int pos, final int i) {
+ buf[pos] = (byte) (i >> 24);
+ buf[pos + 1] = (byte) (i >> 16);
+ buf[pos + 2] = (byte) (i >> 8);
+ buf[pos + 3] = (byte) i;
+ }
+
+ private static int readInt(final byte[] buf, final int pos) {
+ return (buf[pos] & 0xFF) << 24 | (buf[pos + 1] & 0xFF) << 16 | (buf[pos + 2] & 0xFF) << 8 | (buf[pos + 3] & 0xFF);
+ }
+
+ static {
+ (entityIds = new int[256][])[5] = new int[] { 1 };
+ EntityMap.entityIds[7] = new int[] { 1, 5 };
+ EntityMap.entityIds[17] = new int[] { 1 };
+ EntityMap.entityIds[18] = new int[] { 1 };
+ EntityMap.entityIds[19] = new int[] { 1 };
+ EntityMap.entityIds[20] = new int[] { 1 };
+ EntityMap.entityIds[22] = new int[] { 1, 5 };
+ EntityMap.entityIds[23] = new int[] { 1 };
+ EntityMap.entityIds[24] = new int[] { 1 };
+ EntityMap.entityIds[25] = new int[] { 1 };
+ EntityMap.entityIds[26] = new int[] { 1 };
+ EntityMap.entityIds[28] = new int[] { 1 };
+ EntityMap.entityIds[30] = new int[] { 1 };
+ EntityMap.entityIds[31] = new int[] { 1 };
+ EntityMap.entityIds[32] = new int[] { 1 };
+ EntityMap.entityIds[33] = new int[] { 1 };
+ EntityMap.entityIds[34] = new int[] { 1 };
+ EntityMap.entityIds[35] = new int[] { 1 };
+ EntityMap.entityIds[38] = new int[] { 1 };
+ EntityMap.entityIds[39] = new int[] { 1, 5 };
+ EntityMap.entityIds[40] = new int[] { 1 };
+ EntityMap.entityIds[41] = new int[] { 1 };
+ EntityMap.entityIds[42] = new int[] { 1 };
+ EntityMap.entityIds[55] = new int[] { 1 };
+ EntityMap.entityIds[71] = new int[] { 1 };
+ }
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/PacketConstants.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/PacketConstants.java
new file mode 100644
index 0000000..1bfe72f
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/PacketConstants.java
@@ -0,0 +1,25 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee;
+
+import net.md_5.bungee.protocol.packet.PacketFAPluginMessage;
+import net.md_5.bungee.protocol.packet.PacketCDClientStatus;
+import net.md_5.bungee.protocol.packet.Packet9Respawn;
+
+public class PacketConstants {
+ public static final Packet9Respawn DIM1_SWITCH;
+ public static final Packet9Respawn DIM2_SWITCH;
+ public static final PacketCDClientStatus CLIENT_LOGIN;
+ public static final PacketFAPluginMessage FORGE_MOD_REQUEST;
+ public static final PacketFAPluginMessage I_AM_BUNGEE;
+
+ static {
+ DIM1_SWITCH = new Packet9Respawn(1, (byte) 0, (byte) 0, (short) 256, "DEFAULT");
+ DIM2_SWITCH = new Packet9Respawn(-1, (byte) 0, (byte) 0, (short) 256, "DEFAULT");
+ CLIENT_LOGIN = new PacketCDClientStatus((byte) 0);
+ FORGE_MOD_REQUEST = new PacketFAPluginMessage("FML", new byte[] { 0, 0, 0, 0, 0, 2 });
+ I_AM_BUNGEE = new PacketFAPluginMessage("BungeeCord", new byte[0]);
+ }
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/ServerConnection.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/ServerConnection.java
new file mode 100644
index 0000000..9a8f52b
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/ServerConnection.java
@@ -0,0 +1,79 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee;
+
+import java.beans.ConstructorProperties;
+import java.net.InetSocketAddress;
+import java.util.concurrent.TimeUnit;
+import net.md_5.bungee.protocol.packet.PacketFFKick;
+import net.md_5.bungee.protocol.packet.DefinedPacket;
+import net.md_5.bungee.protocol.packet.PacketFAPluginMessage;
+import net.md_5.bungee.api.connection.Connection;
+import net.md_5.bungee.netty.ChannelWrapper;
+import net.md_5.bungee.api.connection.Server;
+
+public class ServerConnection implements Server {
+ private final ChannelWrapper ch;
+ private final BungeeServerInfo info;
+ private boolean isObsolete;
+ private final Connection.Unsafe unsafe;
+
+ @Override
+ public void sendData(final String channel, final byte[] data) {
+ this.unsafe().sendPacket(new PacketFAPluginMessage(channel, data));
+ }
+
+ @Override
+ public synchronized void disconnect(final String reason) {
+ if (!this.ch.isClosed()) {
+ this.unsafe().sendPacket(new PacketFFKick(reason));
+ this.ch.getHandle().eventLoop().schedule((Runnable) new Runnable() {
+ @Override
+ public void run() {
+ ServerConnection.this.ch.getHandle().close();
+ }
+ }, 100L, TimeUnit.MILLISECONDS);
+ }
+ }
+
+ @Override
+ public InetSocketAddress getAddress() {
+ return this.getInfo().getAddress();
+ }
+
+ @Override
+ public Connection.Unsafe unsafe() {
+ return this.unsafe;
+ }
+
+ @ConstructorProperties({ "ch", "info" })
+ public ServerConnection(final ChannelWrapper ch, final BungeeServerInfo info) {
+ this.unsafe = new Connection.Unsafe() {
+ @Override
+ public void sendPacket(final DefinedPacket packet) {
+ ServerConnection.this.ch.write(packet);
+ }
+ };
+ this.ch = ch;
+ this.info = info;
+ }
+
+ public ChannelWrapper getCh() {
+ return this.ch;
+ }
+
+ @Override
+ public BungeeServerInfo getInfo() {
+ return this.info;
+ }
+
+ public boolean isObsolete() {
+ return this.isObsolete;
+ }
+
+ public void setObsolete(final boolean isObsolete) {
+ this.isObsolete = isObsolete;
+ }
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/ServerConnector.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/ServerConnector.java
new file mode 100644
index 0000000..88f5f15
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/ServerConnector.java
@@ -0,0 +1,253 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee;
+
+import java.beans.ConstructorProperties;
+import com.google.common.io.ByteArrayDataInput;
+import net.md_5.bungee.protocol.Protocol;
+import net.md_5.bungee.api.config.ServerInfo;
+import net.md_5.bungee.api.event.ServerKickEvent;
+import java.util.Objects;
+import net.md_5.bungee.protocol.packet.PacketFFKick;
+import net.md_5.bungee.netty.CipherDecoder;
+import javax.crypto.Cipher;
+import java.security.PublicKey;
+import io.netty.channel.ChannelHandler;
+import net.md_5.bungee.netty.CipherEncoder;
+import net.md_5.bungee.netty.PipelineUtils;
+import net.md_5.bungee.protocol.packet.PacketFCEncryptionResponse;
+import java.security.Key;
+import net.md_5.bungee.protocol.packet.PacketFDEncryptionRequest;
+import net.md_5.bungee.api.score.Scoreboard;
+import java.util.Iterator;
+import java.util.Queue;
+import net.md_5.bungee.connection.CancelSendSignal;
+import net.md_5.bungee.api.event.ServerSwitchEvent;
+import net.md_5.bungee.connection.DownstreamBridge;
+import net.md_5.bungee.netty.HandlerBoss;
+import net.md_5.bungee.protocol.packet.Packet9Respawn;
+import net.md_5.bungee.protocol.packet.PacketD1Team;
+import net.md_5.bungee.api.score.Team;
+import net.md_5.bungee.protocol.packet.PacketCEScoreboardObjective;
+import net.md_5.bungee.api.score.Objective;
+import net.md_5.bungee.protocol.packet.DefinedPacket;
+import net.md_5.bungee.protocol.packet.forge.Forge1Login;
+import net.md_5.bungee.protocol.Forge;
+import net.md_5.bungee.netty.PacketDecoder;
+import net.md_5.bungee.api.connection.Server;
+import net.md_5.bungee.api.connection.ProxiedPlayer;
+import net.md_5.bungee.api.event.ServerConnectedEvent;
+import com.google.common.base.Preconditions;
+import net.md_5.bungee.protocol.packet.Packet1Login;
+import com.google.common.io.ByteArrayDataOutput;
+import net.md_5.bungee.protocol.packet.PacketFAPluginMessage;
+import com.google.common.io.ByteStreams;
+import net.md_5.bungee.api.ChatColor;
+import javax.crypto.SecretKey;
+import net.md_5.bungee.netty.ChannelWrapper;
+import net.md_5.bungee.api.ProxyServer;
+import net.md_5.bungee.netty.PacketHandler;
+
+public class ServerConnector extends PacketHandler
+{
+ private final ProxyServer bungee;
+ private ChannelWrapper ch;
+ private final UserConnection user;
+ private final BungeeServerInfo target;
+ private State thisState;
+ private SecretKey secretkey;
+ private boolean sentMessages;
+
+ @Override
+ public void exception(final Throwable t) throws Exception {
+ final String message = "Exception Connecting:" + Util.exception(t);
+ if (this.user.getServer() == null) {
+ this.user.disconnect(message);
+ }
+ else {
+ this.user.sendMessage(ChatColor.RED + message);
+ }
+ }
+
+ @Override
+ public void connected(final ChannelWrapper channel) throws Exception {
+ this.ch = channel;
+ final ByteArrayDataOutput out = ByteStreams.newDataOutput();
+ out.writeUTF("Login");
+ out.writeUTF(this.user.getAddress().getHostString());
+ out.writeInt(this.user.getAddress().getPort());
+ channel.write(new PacketFAPluginMessage("BungeeCord", out.toByteArray()));
+ channel.write(this.user.getPendingConnection().getHandshake());
+ if (this.user.getPendingConnection().getForgeLogin() == null) {
+ channel.write(PacketConstants.CLIENT_LOGIN);
+ }
+ }
+
+ @Override
+ public void disconnected(final ChannelWrapper channel) throws Exception {
+ this.user.getPendingConnects().remove(this.target);
+ }
+
+ @Override
+ public void handle(final Packet1Login login) throws Exception {
+ Preconditions.checkState(this.thisState == State.LOGIN, (Object)"Not exepcting LOGIN");
+ final ServerConnection server = new ServerConnection(this.ch, this.target);
+ final ServerConnectedEvent event = new ServerConnectedEvent(this.user, server);
+ this.bungee.getPluginManager().callEvent(event);
+ this.ch.write(BungeeCord.getInstance().registerChannels());
+ final Queue packetQueue = this.target.getPacketQueue();
+ synchronized (packetQueue) {
+ while (!packetQueue.isEmpty()) {
+ this.ch.write(packetQueue.poll());
+ }
+ }
+ for (final PacketFAPluginMessage message : this.user.getPendingConnection().getRegisterMessages()) {
+ this.ch.write(message);
+ }
+ if (!this.sentMessages) {
+ for (final PacketFAPluginMessage message : this.user.getPendingConnection().getLoginMessages()) {
+ this.ch.write(message);
+ }
+ }
+ if (this.user.getSettings() != null) {
+ this.ch.write(this.user.getSettings());
+ }
+ synchronized (this.user.getSwitchMutex()) {
+ if (this.user.getServer() == null) {
+ this.user.setClientEntityId(login.getEntityId());
+ this.user.setServerEntityId(login.getEntityId());
+ Packet1Login modLogin;
+ if (((PacketDecoder)this.ch.getHandle().pipeline().get((Class)PacketDecoder.class)).getProtocol() == Forge.getInstance()) {
+ modLogin = new Forge1Login(login.getEntityId(), login.getLevelType(), login.getGameMode(), login.getDimension(), login.getDifficulty(), login.getUnused(), (byte)this.user.getPendingConnection().getListener().getTabListSize());
+ }
+ else {
+ modLogin = new Packet1Login(login.getEntityId(), login.getLevelType(), login.getGameMode(), (byte)login.getDimension(), login.getDifficulty(), login.getUnused(), (byte)this.user.getPendingConnection().getListener().getTabListSize());
+ }
+ this.user.unsafe().sendPacket(modLogin);
+ }
+ else {
+ this.user.getTabList().onServerChange();
+ final Scoreboard serverScoreboard = this.user.getServerSentScoreboard();
+ for (final Objective objective : serverScoreboard.getObjectives()) {
+ this.user.unsafe().sendPacket(new PacketCEScoreboardObjective(objective.getName(), objective.getValue(), (byte)1));
+ }
+ for (final Team team : serverScoreboard.getTeams()) {
+ this.user.unsafe().sendPacket(new PacketD1Team(team.getName()));
+ }
+ serverScoreboard.clear();
+ this.user.sendDimensionSwitch();
+ this.user.setServerEntityId(login.getEntityId());
+ this.user.unsafe().sendPacket(new Packet9Respawn(login.getDimension(), login.getDifficulty(), login.getGameMode(), (short)256, login.getLevelType()));
+ this.user.getServer().setObsolete(true);
+ this.user.getServer().disconnect("Quitting");
+ }
+ if (!this.user.isActive()) {
+ server.disconnect("Quitting");
+ this.bungee.getLogger().warning("No client connected for pending server!");
+ return;
+ }
+ this.target.addPlayer(this.user);
+ this.user.getPendingConnects().remove(this.target);
+ this.user.setServer(server);
+ ((HandlerBoss)this.ch.getHandle().pipeline().get((Class)HandlerBoss.class)).setHandler(new DownstreamBridge(this.bungee, this.user, server));
+ }
+ this.bungee.getPluginManager().callEvent(new ServerSwitchEvent(this.user));
+ this.thisState = State.FINISHED;
+ throw new CancelSendSignal();
+ }
+
+ @Override
+ public void handle(final PacketFDEncryptionRequest encryptRequest) throws Exception {
+ Preconditions.checkState(this.thisState == State.ENCRYPT_REQUEST, (Object)"Not expecting ENCRYPT_REQUEST");
+ if (this.user.getPendingConnection().getForgeLogin() != null) {
+ final PublicKey publickey = EncryptionUtil.getPubkey(encryptRequest);
+ this.secretkey = EncryptionUtil.getSecret();
+ final byte[] shared = EncryptionUtil.encrypt(publickey, this.secretkey.getEncoded());
+ final byte[] token = EncryptionUtil.encrypt(publickey, encryptRequest.getVerifyToken());
+ this.ch.write(new PacketFCEncryptionResponse(shared, token));
+ final Cipher encrypt = EncryptionUtil.getCipher(1, this.secretkey);
+ this.ch.getHandle().pipeline().addBefore(PipelineUtils.PACKET_DECODE_HANDLER, PipelineUtils.ENCRYPT_HANDLER, (ChannelHandler)new CipherEncoder(encrypt));
+ this.thisState = State.ENCRYPT_RESPONSE;
+ }
+ else {
+ this.thisState = State.LOGIN;
+ }
+ }
+
+ @Override
+ public void handle(final PacketFCEncryptionResponse encryptResponse) throws Exception {
+ Preconditions.checkState(this.thisState == State.ENCRYPT_RESPONSE, (Object)"Not expecting ENCRYPT_RESPONSE");
+ final Cipher decrypt = EncryptionUtil.getCipher(2, this.secretkey);
+ this.ch.getHandle().pipeline().addBefore(PipelineUtils.PACKET_DECODE_HANDLER, PipelineUtils.DECRYPT_HANDLER, (ChannelHandler)new CipherDecoder(decrypt));
+ this.ch.write(this.user.getPendingConnection().getForgeLogin());
+ this.ch.write(PacketConstants.CLIENT_LOGIN);
+ this.thisState = State.LOGIN;
+ }
+
+ @Override
+ public void handle(final PacketFFKick kick) throws Exception {
+ ServerInfo def = this.bungee.getServerInfo(this.user.getPendingConnection().getListener().getFallbackServer());
+ if (Objects.equals(this.target, def)) {
+ def = null;
+ }
+ final ServerKickEvent event = this.bungee.getPluginManager().callEvent(new ServerKickEvent(this.user, kick.getMessage(), def));
+ if (event.isCancelled() && event.getCancelServer() != null) {
+ this.user.connect(event.getCancelServer());
+ return;
+ }
+ final String message = this.bungee.getTranslation("connect_kick") + this.target.getName() + ": " + kick.getMessage();
+ if (this.user.getServer() == null) {
+ this.user.disconnect(message);
+ }
+ else {
+ this.user.sendMessage(message);
+ }
+ }
+
+ @Override
+ public void handle(final PacketFAPluginMessage pluginMessage) throws Exception {
+ if (pluginMessage.equals(PacketConstants.I_AM_BUNGEE)) {
+ throw new IllegalStateException("May not connect to another BungeCord!");
+ }
+ if (pluginMessage.getTag().equals("FML") && (pluginMessage.getData()[0] & 0xFF) == 0x0) {
+ final ByteArrayDataInput in = ByteStreams.newDataInput(pluginMessage.getData());
+ in.readUnsignedByte();
+ for (int count = in.readInt(), i = 0; i < count; ++i) {
+ in.readUTF();
+ }
+ if (in.readByte() != 0) {
+ ((PacketDecoder)this.ch.getHandle().pipeline().get((Class)PacketDecoder.class)).setProtocol(Forge.getInstance());
+ }
+ }
+ this.user.unsafe().sendPacket(pluginMessage);
+ if (!this.sentMessages && this.user.getPendingConnection().getForgeLogin() != null) {
+ for (final PacketFAPluginMessage message : this.user.getPendingConnection().getLoginMessages()) {
+ this.ch.write(message);
+ }
+ this.sentMessages = true;
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "[" + this.user.getName() + "] <-> ServerConnector [" + this.target.getName() + "]";
+ }
+
+ @ConstructorProperties({ "bungee", "user", "target" })
+ public ServerConnector(final ProxyServer bungee, final UserConnection user, final BungeeServerInfo target) {
+ this.thisState = State.ENCRYPT_REQUEST;
+ this.bungee = bungee;
+ this.user = user;
+ this.target = target;
+ }
+
+ private enum State
+ {
+ ENCRYPT_REQUEST,
+ ENCRYPT_RESPONSE,
+ LOGIN,
+ FINISHED;
+ }
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/UserConnection.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/UserConnection.java
new file mode 100644
index 0000000..cb3d9da
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/UserConnection.java
@@ -0,0 +1,386 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee;
+
+import net.md_5.bungee.api.connection.Server;
+import net.md_5.bungee.api.connection.PendingConnection;
+import java.beans.ConstructorProperties;
+import net.md_5.bungee.util.CaseInsensitiveSet;
+import java.util.HashSet;
+import net.md_5.bungee.api.config.TexturePackInfo;
+import net.md_5.bungee.api.CommandSender;
+import net.md_5.bungee.api.event.PermissionCheckEvent;
+import java.util.Collections;
+import java.net.InetSocketAddress;
+import net.md_5.bungee.protocol.packet.PacketFAPluginMessage;
+import net.md_5.bungee.protocol.packet.Packet3Chat;
+import net.md_5.bungee.protocol.packet.PacketFFKick;
+import java.util.logging.Level;
+import io.netty.util.concurrent.GenericFutureListener;
+import io.netty.util.internal.PlatformDependent;
+import java.net.SocketAddress;
+import io.netty.channel.ChannelOption;
+import io.netty.channel.ChannelHandler;
+import io.netty.channel.EventLoopGroup;
+import io.netty.channel.socket.nio.NioSocketChannel;
+import io.netty.bootstrap.Bootstrap;
+import io.netty.util.concurrent.Future;
+import io.netty.channel.ChannelFuture;
+import io.netty.channel.ChannelFutureListener;
+import net.md_5.bungee.netty.PacketHandler;
+import net.md_5.bungee.netty.HandlerBoss;
+import net.md_5.bungee.netty.PipelineUtils;
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelInitializer;
+import net.md_5.bungee.api.ChatColor;
+import java.util.Objects;
+import net.md_5.bungee.api.event.ServerConnectEvent;
+import net.md_5.bungee.protocol.packet.DefinedPacket;
+import com.google.common.base.Preconditions;
+import java.util.Iterator;
+import net.md_5.bungee.api.connection.Connection;
+import net.md_5.bungee.api.score.Scoreboard;
+import net.md_5.bungee.protocol.packet.PacketCCSettings;
+import net.md_5.bungee.api.tab.TabListHandler;
+import net.md_5.bungee.api.config.ServerInfo;
+import java.util.Collection;
+import net.md_5.bungee.connection.InitialHandler;
+import net.md_5.bungee.netty.ChannelWrapper;
+import net.md_5.bungee.api.ProxyServer;
+import net.md_5.bungee.api.connection.ProxiedPlayer;
+
+public final class UserConnection implements ProxiedPlayer {
+ private final ProxyServer bungee;
+ private final ChannelWrapper ch;
+ private final String name;
+ private final InitialHandler pendingConnection;
+ private ServerConnection server;
+ private final Object switchMutex;
+ private final Collection pendingConnects;
+ private TabListHandler tabList;
+ private int sentPingId;
+ private long sentPingTime;
+ private int ping;
+ private final Collection groups;
+ private final Collection permissions;
+ private int clientEntityId;
+ private int serverEntityId;
+ private PacketCCSettings settings;
+ private final Scoreboard serverSentScoreboard;
+ private String displayName;
+ private final Connection.Unsafe unsafe;
+
+ public void init() {
+ this.displayName = this.name;
+ try {
+ this.tabList = (TabListHandler) this.getPendingConnection().getListener().getTabList().getDeclaredConstructor((Class>[]) new Class[0]).newInstance(new Object[0]);
+ } catch (ReflectiveOperationException ex) {
+ throw new RuntimeException(ex);
+ }
+ this.tabList.init(this);
+ final Collection g = this.bungee.getConfigurationAdapter().getGroups(this.name);
+ for (final String s : g) {
+ this.addGroups(s);
+ }
+ }
+
+ @Override
+ public void setTabList(final TabListHandler tabList) {
+ tabList.init(this);
+ this.tabList = tabList;
+ }
+
+ public void sendPacket(final byte[] b) {
+ this.ch.write(b);
+ }
+
+ @Deprecated
+ public boolean isActive() {
+ return !this.ch.isClosed();
+ }
+
+ @Override
+ public void setDisplayName(final String name) {
+ Preconditions.checkNotNull((Object) name, (Object) "displayName");
+ Preconditions.checkArgument(name.length() <= 16, (Object) "Display name cannot be longer than 16 characters");
+ this.getTabList().onDisconnect();
+ this.displayName = name;
+ this.getTabList().onConnect();
+ }
+
+ @Override
+ public void connect(final ServerInfo target) {
+ this.connect(target, false);
+ }
+
+ void sendDimensionSwitch() {
+ this.unsafe().sendPacket(PacketConstants.DIM1_SWITCH);
+ this.unsafe().sendPacket(PacketConstants.DIM2_SWITCH);
+ }
+
+ public void connectNow(final ServerInfo target) {
+ this.sendDimensionSwitch();
+ this.connect(target);
+ }
+
+ public void connect(final ServerInfo info, final boolean retry) {
+ final ServerConnectEvent event = new ServerConnectEvent(this, info);
+ if (this.bungee.getPluginManager().callEvent(event).isCancelled()) {
+ return;
+ }
+ final BungeeServerInfo target = (BungeeServerInfo) event.getTarget();
+ if (this.getServer() != null && Objects.equals(this.getServer().getInfo(), target)) {
+ //this.sendMessage(ChatColor.RED + "Cannot connect to server you are already on!");
+ return;
+ }
+ if (this.pendingConnects.contains(target)) {
+ this.sendMessage(ChatColor.RED + "Already connecting to this server!");
+ return;
+ }
+ this.pendingConnects.add(target);
+ final ChannelInitializer initializer = new ChannelInitializer() {
+ protected void initChannel(final Channel ch) throws Exception {
+ PipelineUtils.BASE.initChannel(ch);
+ ((HandlerBoss) ch.pipeline().get((Class) HandlerBoss.class)).setHandler(new ServerConnector(UserConnection.this.bungee, UserConnection.this, target));
+ }
+ };
+ final ChannelFutureListener listener = (ChannelFutureListener) new ChannelFutureListener() {
+ public void operationComplete(final ChannelFuture future) throws Exception {
+ if (!future.isSuccess()) {
+ future.channel().close();
+ UserConnection.this.pendingConnects.remove(target);
+ final ServerInfo def = ProxyServer.getInstance().getServers().get(UserConnection.this.getPendingConnection().getListener().getFallbackServer());
+ if ((retry & target != def) && (UserConnection.this.getServer() == null || def != UserConnection.this.getServer().getInfo())) {
+ UserConnection.this.sendMessage(UserConnection.this.bungee.getTranslation("fallback_lobby"));
+ UserConnection.this.connect(def, false);
+ } else if (UserConnection.this.server == null) {
+ UserConnection.this.disconnect(UserConnection.this.bungee.getTranslation("fallback_kick") + future.cause().getClass().getName());
+ } else {
+ UserConnection.this.sendMessage(UserConnection.this.bungee.getTranslation("fallback_kick") + future.cause().getClass().getName());
+ }
+ }
+ }
+ };
+ final Bootstrap b = ((Bootstrap) ((Bootstrap) ((Bootstrap) ((Bootstrap) new Bootstrap().channel((Class) NioSocketChannel.class)).group((EventLoopGroup) BungeeCord.getInstance().eventLoops)).handler((ChannelHandler) initializer))
+ .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, Integer.valueOf(5000))).remoteAddress((SocketAddress) target.getAddress());
+ if (!PlatformDependent.isWindows()) {
+ b.localAddress(this.getPendingConnection().getListener().getHost().getHostString(), 0);
+ }
+ b.connect().addListener((GenericFutureListener) listener);
+ }
+
+ @Override
+ public synchronized void disconnect(final String reason) {
+ if (this.ch.getHandle().isActive()) {
+ this.bungee.getLogger().log(Level.INFO, "[" + this.getName() + "] disconnected with: " + reason);
+ this.unsafe().sendPacket(new PacketFFKick(reason));
+ this.ch.close();
+ if (this.server != null) {
+ this.server.disconnect("Quitting");
+ }
+ }
+ }
+
+ @Override
+ public void chat(final String message) {
+ Preconditions.checkState(this.server != null, (Object) "Not connected to server");
+ this.server.getCh().write(new Packet3Chat(message));
+ }
+
+ @Override
+ public void sendMessage(final String message) {
+ this.unsafe().sendPacket(new Packet3Chat(message));
+ }
+
+ @Override
+ public void sendMessages(final String... messages) {
+ for (final String message : messages) {
+ this.sendMessage(message);
+ }
+ }
+
+ @Override
+ public void sendData(final String channel, final byte[] data) {
+ this.unsafe().sendPacket(new PacketFAPluginMessage(channel, data));
+ }
+
+ @Override
+ public InetSocketAddress getAddress() {
+ return (InetSocketAddress) this.ch.getHandle().remoteAddress();
+ }
+
+ @Override
+ public Collection getGroups() {
+ return Collections.unmodifiableCollection((Collection extends String>) this.groups);
+ }
+
+ @Override
+ public void addGroups(final String... groups) {
+ for (final String group : groups) {
+ this.groups.add(group);
+ for (final String permission : this.bungee.getConfigurationAdapter().getPermissions(group)) {
+ this.setPermission(permission, true);
+ }
+ }
+ }
+
+ @Override
+ public void removeGroups(final String... groups) {
+ for (final String group : groups) {
+ this.groups.remove(group);
+ for (final String permission : this.bungee.getConfigurationAdapter().getPermissions(group)) {
+ this.setPermission(permission, false);
+ }
+ }
+ }
+
+ @Override
+ public boolean hasPermission(final String permission) {
+ return this.bungee.getPluginManager().callEvent(new PermissionCheckEvent(this, permission, this.permissions.contains(permission))).hasPermission();
+ }
+
+ @Override
+ public void setPermission(final String permission, final boolean value) {
+ if (value) {
+ this.permissions.add(permission);
+ } else {
+ this.permissions.remove(permission);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return this.name;
+ }
+
+ @Override
+ public void setTexturePack(final TexturePackInfo pack) {
+ this.unsafe().sendPacket(new PacketFAPluginMessage("MC|TPack", (pack.getUrl() + "\u0000" + pack.getSize()).getBytes()));
+ }
+
+ @Override
+ public Connection.Unsafe unsafe() {
+ return this.unsafe;
+ }
+
+ @ConstructorProperties({ "bungee", "ch", "name", "pendingConnection" })
+ public UserConnection(final ProxyServer bungee, final ChannelWrapper ch, final String name, final InitialHandler pendingConnection) {
+ this.switchMutex = new Object();
+ this.pendingConnects = new HashSet();
+ this.ping = 100;
+ this.groups = (Collection) new CaseInsensitiveSet();
+ this.permissions = (Collection) new CaseInsensitiveSet();
+ this.serverSentScoreboard = new Scoreboard();
+ this.unsafe = new Connection.Unsafe() {
+ @Override
+ public void sendPacket(final DefinedPacket packet) {
+ UserConnection.this.ch.write(packet);
+ }
+ };
+ if (bungee == null) {
+ throw new NullPointerException("bungee");
+ }
+ if (ch == null) {
+ throw new NullPointerException("ch");
+ }
+ if (name == null) {
+ throw new NullPointerException("name");
+ }
+ this.bungee = bungee;
+ this.ch = ch;
+ this.name = name;
+ this.pendingConnection = pendingConnection;
+ }
+
+ @Override
+ public String getName() {
+ return this.name;
+ }
+
+ @Override
+ public InitialHandler getPendingConnection() {
+ return this.pendingConnection;
+ }
+
+ @Override
+ public ServerConnection getServer() {
+ return this.server;
+ }
+
+ public void setServer(final ServerConnection server) {
+ this.server = server;
+ }
+
+ public Object getSwitchMutex() {
+ return this.switchMutex;
+ }
+
+ public Collection getPendingConnects() {
+ return this.pendingConnects;
+ }
+
+ @Override
+ public TabListHandler getTabList() {
+ return this.tabList;
+ }
+
+ public int getSentPingId() {
+ return this.sentPingId;
+ }
+
+ public void setSentPingId(final int sentPingId) {
+ this.sentPingId = sentPingId;
+ }
+
+ public long getSentPingTime() {
+ return this.sentPingTime;
+ }
+
+ public void setSentPingTime(final long sentPingTime) {
+ this.sentPingTime = sentPingTime;
+ }
+
+ @Override
+ public int getPing() {
+ return this.ping;
+ }
+
+ public void setPing(final int ping) {
+ this.ping = ping;
+ }
+
+ public int getClientEntityId() {
+ return this.clientEntityId;
+ }
+
+ public void setClientEntityId(final int clientEntityId) {
+ this.clientEntityId = clientEntityId;
+ }
+
+ public int getServerEntityId() {
+ return this.serverEntityId;
+ }
+
+ public void setServerEntityId(final int serverEntityId) {
+ this.serverEntityId = serverEntityId;
+ }
+
+ public PacketCCSettings getSettings() {
+ return this.settings;
+ }
+
+ public void setSettings(final PacketCCSettings settings) {
+ this.settings = settings;
+ }
+
+ public Scoreboard getServerSentScoreboard() {
+ return this.serverSentScoreboard;
+ }
+
+ @Override
+ public String getDisplayName() {
+ return this.displayName;
+ }
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/Util.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/Util.java
new file mode 100644
index 0000000..4d8e43f
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/Util.java
@@ -0,0 +1,44 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee;
+
+import java.util.Iterator;
+import java.util.Collection;
+import java.net.InetSocketAddress;
+
+public class Util {
+ private static final int DEFAULT_PORT = 25565;
+
+ public static InetSocketAddress getAddr(final String hostline) {
+ final String[] split = hostline.split(":");
+ int port = 25565;
+ if (split.length > 1) {
+ port = Integer.parseInt(split[1]);
+ }
+ return new InetSocketAddress(split[0], port);
+ }
+
+ public static String hex(final int i) {
+ return String.format("0x%02X", i);
+ }
+
+ public static String exception(final Throwable t) {
+ final StackTraceElement[] trace = t.getStackTrace();
+ return t.getClass().getSimpleName() + " : " + t.getMessage() + ((trace.length > 0) ? (" @ " + t.getStackTrace()[0].getClassName() + ":" + t.getStackTrace()[0].getLineNumber()) : "");
+ }
+
+ public static String csv(final Collection> objects) {
+ return format(objects, ", ");
+ }
+
+ public static String format(final Collection> objects, final String separators) {
+ final StringBuilder ret = new StringBuilder();
+ for (final Object o : objects) {
+ ret.append(o);
+ ret.append(separators);
+ }
+ return (ret.length() == 0) ? "" : ret.substring(0, ret.length() - separators.length());
+ }
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/api/Callback.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/Callback.java
new file mode 100644
index 0000000..2291dd0
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/Callback.java
@@ -0,0 +1,9 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.api;
+
+public interface Callback {
+ void done(final V p0, final Throwable p1);
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/api/ChatColor.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/ChatColor.java
new file mode 100644
index 0000000..cda85ac
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/ChatColor.java
@@ -0,0 +1,60 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.api;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+public enum ChatColor {
+ BLACK('0'), DARK_BLUE('1'), DARK_GREEN('2'), DARK_AQUA('3'), DARK_RED('4'), DARK_PURPLE('5'), GOLD('6'), GRAY('7'), DARK_GRAY('8'), BLUE('9'), GREEN('a'), AQUA('b'), RED('c'), LIGHT_PURPLE('d'), YELLOW('e'), WHITE('f'), MAGIC('k'),
+ BOLD('l'), STRIKETHROUGH('m'), UNDERLINE('n'), ITALIC('o'), RESET('r');
+
+ public static final char COLOR_CHAR = '§';
+ private static final Pattern STRIP_COLOR_PATTERN;
+ private static final Map BY_CHAR;
+ private final char code;
+ private final String toString;
+
+ private ChatColor(final char code) {
+ this.code = code;
+ this.toString = new String(new char[] { '§', code });
+ }
+
+ @Override
+ public String toString() {
+ return this.toString;
+ }
+
+ public static String stripColor(final String input) {
+ if (input == null) {
+ return null;
+ }
+ return ChatColor.STRIP_COLOR_PATTERN.matcher(input).replaceAll("");
+ }
+
+ public static String translateAlternateColorCodes(final char altColorChar, final String textToTranslate) {
+ final 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] = '§';
+ b[i + 1] = Character.toLowerCase(b[i + 1]);
+ }
+ }
+ return new String(b);
+ }
+
+ public static ChatColor getByChar(final char code) {
+ return ChatColor.BY_CHAR.get(code);
+ }
+
+ static {
+ STRIP_COLOR_PATTERN = Pattern.compile("(?i)" + String.valueOf('§') + "[0-9A-FK-OR]");
+ BY_CHAR = new HashMap();
+ for (final ChatColor colour : values()) {
+ ChatColor.BY_CHAR.put(colour.code, colour);
+ }
+ }
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/api/CommandSender.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/CommandSender.java
new file mode 100644
index 0000000..7f93805
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/CommandSender.java
@@ -0,0 +1,25 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.api;
+
+import java.util.Collection;
+
+public interface CommandSender {
+ String getName();
+
+ void sendMessage(final String p0);
+
+ void sendMessages(final String... p0);
+
+ Collection getGroups();
+
+ void addGroups(final String... p0);
+
+ void removeGroups(final String... p0);
+
+ boolean hasPermission(final String p0);
+
+ void setPermission(final String p0, final boolean p1);
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/api/ProxyServer.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/ProxyServer.java
new file mode 100644
index 0000000..493de3f
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/ProxyServer.java
@@ -0,0 +1,86 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.api;
+
+import net.md_5.bungee.api.tab.CustomTabList;
+import net.md_5.bungee.api.scheduler.TaskScheduler;
+import java.io.File;
+import java.net.InetSocketAddress;
+import net.md_5.bungee.api.config.ConfigurationAdapter;
+import net.md_5.bungee.api.plugin.PluginManager;
+import net.md_5.bungee.api.config.ServerInfo;
+import java.util.Map;
+import net.md_5.bungee.api.connection.ProxiedPlayer;
+import java.util.Collection;
+import java.util.logging.Logger;
+import com.google.common.base.Preconditions;
+
+public abstract class ProxyServer {
+ private static ProxyServer instance;
+
+ public static void setInstance(final ProxyServer instance) {
+ Preconditions.checkNotNull((Object) instance, (Object) "instance");
+ Preconditions.checkArgument(ProxyServer.instance == null, (Object) "Instance already set");
+ ProxyServer.instance = instance;
+ }
+
+ public abstract String getName();
+
+ public abstract String getVersion();
+
+ public abstract String getTranslation(final String p0);
+
+ public abstract Logger getLogger();
+
+ public abstract Collection getPlayers();
+
+ public abstract ProxiedPlayer getPlayer(final String p0);
+
+ public abstract Map getServers();
+
+ public abstract ServerInfo getServerInfo(final String p0);
+
+ public abstract PluginManager getPluginManager();
+
+ public abstract ConfigurationAdapter getConfigurationAdapter();
+
+ public abstract void setConfigurationAdapter(final ConfigurationAdapter p0);
+
+ public abstract ReconnectHandler getReconnectHandler();
+
+ public abstract void setReconnectHandler(final ReconnectHandler p0);
+
+ public abstract void stop();
+
+ public abstract void start() throws Exception;
+
+ public abstract void registerChannel(final String p0);
+
+ public abstract void unregisterChannel(final String p0);
+
+ public abstract Collection getChannels();
+
+ public abstract String getGameVersion();
+
+ public abstract byte getProtocolVersion();
+
+ public abstract ServerInfo constructServerInfo(final String p0, final InetSocketAddress p1, final boolean p2);
+
+ public abstract CommandSender getConsole();
+
+ public abstract File getPluginsFolder();
+
+ public abstract TaskScheduler getScheduler();
+
+ public abstract int getOnlineCount();
+
+ public abstract void broadcast(final String p0);
+
+ public abstract CustomTabList customTabList(final ProxiedPlayer p0);
+
+ public static ProxyServer getInstance() {
+ return ProxyServer.instance;
+ }
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/api/ReconnectHandler.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/ReconnectHandler.java
new file mode 100644
index 0000000..3e8c187
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/ReconnectHandler.java
@@ -0,0 +1,18 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.api;
+
+import net.md_5.bungee.api.config.ServerInfo;
+import net.md_5.bungee.api.connection.ProxiedPlayer;
+
+public interface ReconnectHandler {
+ ServerInfo getServer(final ProxiedPlayer p0);
+
+ void setServer(final ProxiedPlayer p0);
+
+ void save();
+
+ void close();
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/api/ServerPing.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/ServerPing.java
new file mode 100644
index 0000000..c729d55
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/ServerPing.java
@@ -0,0 +1,107 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.api;
+
+import java.beans.ConstructorProperties;
+
+public class ServerPing {
+ private final byte protocolVersion;
+ private final String gameVersion;
+ private final String motd;
+ private final int currentPlayers;
+ private final int maxPlayers;
+
+ @ConstructorProperties({ "protocolVersion", "gameVersion", "motd", "currentPlayers", "maxPlayers" })
+ public ServerPing(final byte protocolVersion, final String gameVersion, final String motd, final int currentPlayers, final int maxPlayers) {
+ this.protocolVersion = protocolVersion;
+ this.gameVersion = gameVersion;
+ this.motd = motd;
+ this.currentPlayers = currentPlayers;
+ this.maxPlayers = maxPlayers;
+ }
+
+ public byte getProtocolVersion() {
+ return this.protocolVersion;
+ }
+
+ public String getGameVersion() {
+ return this.gameVersion;
+ }
+
+ public String getMotd() {
+ return this.motd;
+ }
+
+ public int getCurrentPlayers() {
+ return this.currentPlayers;
+ }
+
+ public int getMaxPlayers() {
+ return this.maxPlayers;
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (o == this) {
+ return true;
+ }
+ if (!(o instanceof ServerPing)) {
+ return false;
+ }
+ final ServerPing other = (ServerPing) o;
+ if (!other.canEqual(this)) {
+ return false;
+ }
+ if (this.getProtocolVersion() != other.getProtocolVersion()) {
+ return false;
+ }
+ final Object this$gameVersion = this.getGameVersion();
+ final Object other$gameVersion = other.getGameVersion();
+ Label_0078: {
+ if (this$gameVersion == null) {
+ if (other$gameVersion == null) {
+ break Label_0078;
+ }
+ } else if (this$gameVersion.equals(other$gameVersion)) {
+ break Label_0078;
+ }
+ return false;
+ }
+ final Object this$motd = this.getMotd();
+ final Object other$motd = other.getMotd();
+ if (this$motd == null) {
+ if (other$motd == null) {
+ return this.getCurrentPlayers() == other.getCurrentPlayers() && this.getMaxPlayers() == other.getMaxPlayers();
+ }
+ } else if (this$motd.equals(other$motd)) {
+ return this.getCurrentPlayers() == other.getCurrentPlayers() && this.getMaxPlayers() == other.getMaxPlayers();
+ }
+ return false;
+ }
+
+ public boolean canEqual(final Object other) {
+ return other instanceof ServerPing;
+ }
+
+ @Override
+ public int hashCode() {
+ final int PRIME = 31;
+ int result = 1;
+ result = result * 31 + this.getProtocolVersion();
+ final Object $gameVersion = this.getGameVersion();
+ result = result * 31 + (($gameVersion == null) ? 0 : $gameVersion.hashCode());
+ final Object $motd = this.getMotd();
+ result = result * 31 + (($motd == null) ? 0 : $motd.hashCode());
+ result = result * 31 + this.getCurrentPlayers();
+ result = result * 31 + this.getMaxPlayers();
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "ServerPing(protocolVersion=" + this.getProtocolVersion() + ", gameVersion=" + this.getGameVersion() + ", motd=" + this.getMotd() + ", currentPlayers=" + this.getCurrentPlayers() + ", maxPlayers=" + this.getMaxPlayers()
+ + ")";
+ }
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/api/config/AuthServiceInfo.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/config/AuthServiceInfo.java
new file mode 100644
index 0000000..fd52e63
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/config/AuthServiceInfo.java
@@ -0,0 +1,35 @@
+package net.md_5.bungee.api.config;
+
+import java.io.File;
+
+public class AuthServiceInfo {
+
+ private final boolean enabled;
+ private final String limbo;
+ private final File authfile;
+ private final int timeout;
+
+ public AuthServiceInfo(boolean enabled, String limbo, File authfile, int timeout) {
+ this.enabled = enabled;
+ this.limbo = limbo;
+ this.authfile = authfile;
+ this.timeout = timeout;
+ }
+
+ public boolean isEnabled() {
+ return enabled;
+ }
+
+ public String getLimbo() {
+ return limbo;
+ }
+
+ public File getAuthfile() {
+ return authfile;
+ }
+
+ public int getTimeout() {
+ return timeout;
+ }
+
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/api/config/ConfigurationAdapter.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/config/ConfigurationAdapter.java
new file mode 100644
index 0000000..b57e542
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/config/ConfigurationAdapter.java
@@ -0,0 +1,28 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.api.config;
+
+import java.util.Collection;
+import java.util.Map;
+
+public interface ConfigurationAdapter {
+ void load();
+
+ int getInt(final String p0, final int p1);
+
+ String getString(final String p0, final String p1);
+
+ boolean getBoolean(final String p0, final boolean p1);
+
+ Map getServers();
+
+ Collection getListeners();
+
+ Collection getGroups(final String p0);
+
+ Collection getPermissions(final String p0);
+
+ AuthServiceInfo getAuthSettings();
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/api/config/ListenerInfo.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/config/ListenerInfo.java
new file mode 100644
index 0000000..801c1be
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/config/ListenerInfo.java
@@ -0,0 +1,223 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.api.config;
+
+import java.beans.ConstructorProperties;
+import net.md_5.bungee.api.tab.TabListHandler;
+import java.util.Map;
+import java.net.InetSocketAddress;
+
+public class ListenerInfo {
+ private final InetSocketAddress host;
+ private final String motd;
+ private final int maxPlayers;
+ private final int tabListSize;
+ private final String defaultServer;
+ private final String fallbackServer;
+ private final boolean forceDefault;
+ private final boolean websocket;
+ private final Map forcedHosts;
+ private final TexturePackInfo texturePack;
+ private final Class extends TabListHandler> tabList;
+
+ @ConstructorProperties({ "host", "motd", "maxPlayers", "tabListSize", "defaultServer", "fallbackServer", "forceDefault", "websocket", "forcedHosts", "texturePack", "tabList" })
+ public ListenerInfo(final InetSocketAddress host, final String motd, final int maxPlayers, final int tabListSize, final String defaultServer, final String fallbackServer, final boolean forceDefault, final boolean websocket,
+ final Map forcedHosts, final TexturePackInfo texturePack, final Class extends TabListHandler> tabList) {
+ this.host = host;
+ this.motd = motd;
+ this.maxPlayers = maxPlayers;
+ this.tabListSize = tabListSize;
+ this.defaultServer = defaultServer;
+ this.fallbackServer = fallbackServer;
+ this.forceDefault = forceDefault;
+ this.websocket = websocket;
+ this.forcedHosts = forcedHosts;
+ this.texturePack = texturePack;
+ this.tabList = tabList;
+ }
+
+ public InetSocketAddress getHost() {
+ return this.host;
+ }
+
+ public String getMotd() {
+ return this.motd;
+ }
+
+ public int getMaxPlayers() {
+ return this.maxPlayers;
+ }
+
+ public int getTabListSize() {
+ return this.tabListSize;
+ }
+
+ public String getDefaultServer() {
+ return this.defaultServer;
+ }
+
+ public String getFallbackServer() {
+ return this.fallbackServer;
+ }
+
+ public boolean isForceDefault() {
+ return this.forceDefault;
+ }
+
+ public Map getForcedHosts() {
+ return this.forcedHosts;
+ }
+
+ public TexturePackInfo getTexturePack() {
+ return this.texturePack;
+ }
+
+ public Class extends TabListHandler> getTabList() {
+ return this.tabList;
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (o == this) {
+ return true;
+ }
+ if (!(o instanceof ListenerInfo)) {
+ return false;
+ }
+ final ListenerInfo other = (ListenerInfo) o;
+ if (!other.canEqual(this)) {
+ return false;
+ }
+ final Object this$host = this.getHost();
+ final Object other$host = other.getHost();
+ Label_0065: {
+ if (this$host == null) {
+ if (other$host == null) {
+ break Label_0065;
+ }
+ } else if (this$host.equals(other$host)) {
+ break Label_0065;
+ }
+ return false;
+ }
+ final Object this$motd = this.getMotd();
+ final Object other$motd = other.getMotd();
+ Label_0102: {
+ if (this$motd == null) {
+ if (other$motd == null) {
+ break Label_0102;
+ }
+ } else if (this$motd.equals(other$motd)) {
+ break Label_0102;
+ }
+ return false;
+ }
+ if (this.getMaxPlayers() != other.getMaxPlayers()) {
+ return false;
+ }
+ if (this.getTabListSize() != other.getTabListSize()) {
+ return false;
+ }
+ final Object this$defaultServer = this.getDefaultServer();
+ final Object other$defaultServer = other.getDefaultServer();
+ Label_0165: {
+ if (this$defaultServer == null) {
+ if (other$defaultServer == null) {
+ break Label_0165;
+ }
+ } else if (this$defaultServer.equals(other$defaultServer)) {
+ break Label_0165;
+ }
+ return false;
+ }
+ final Object this$fallbackServer = this.getFallbackServer();
+ final Object other$fallbackServer = other.getFallbackServer();
+ Label_0202: {
+ if (this$fallbackServer == null) {
+ if (other$fallbackServer == null) {
+ break Label_0202;
+ }
+ } else if (this$fallbackServer.equals(other$fallbackServer)) {
+ break Label_0202;
+ }
+ return false;
+ }
+ if (this.isForceDefault() != other.isForceDefault()) {
+ return false;
+ }
+ final Object this$forcedHosts = this.getForcedHosts();
+ final Object other$forcedHosts = other.getForcedHosts();
+ Label_0252: {
+ if (this$forcedHosts == null) {
+ if (other$forcedHosts == null) {
+ break Label_0252;
+ }
+ } else if (this$forcedHosts.equals(other$forcedHosts)) {
+ break Label_0252;
+ }
+ return false;
+ }
+ final Object this$texturePack = this.getTexturePack();
+ final Object other$texturePack = other.getTexturePack();
+ Label_0289: {
+ if (this$texturePack == null) {
+ if (other$texturePack == null) {
+ break Label_0289;
+ }
+ } else if (this$texturePack.equals(other$texturePack)) {
+ break Label_0289;
+ }
+ return false;
+ }
+ final Object this$tabList = this.getTabList();
+ final Object other$tabList = other.getTabList();
+ if (this$tabList == null) {
+ if (other$tabList == null) {
+ return true;
+ }
+ } else if (this$tabList.equals(other$tabList)) {
+ return true;
+ }
+ return false;
+ }
+
+ public boolean canEqual(final Object other) {
+ return other instanceof ListenerInfo;
+ }
+
+ @Override
+ public int hashCode() {
+ final int PRIME = 31;
+ int result = 1;
+ final Object $host = this.getHost();
+ result = result * 31 + (($host == null) ? 0 : $host.hashCode());
+ final Object $motd = this.getMotd();
+ result = result * 31 + (($motd == null) ? 0 : $motd.hashCode());
+ result = result * 31 + this.getMaxPlayers();
+ result = result * 31 + this.getTabListSize();
+ final Object $defaultServer = this.getDefaultServer();
+ result = result * 31 + (($defaultServer == null) ? 0 : $defaultServer.hashCode());
+ final Object $fallbackServer = this.getFallbackServer();
+ result = result * 31 + (($fallbackServer == null) ? 0 : $fallbackServer.hashCode());
+ result = result * 31 + (this.isForceDefault() ? 1231 : 1237);
+ final Object $forcedHosts = this.getForcedHosts();
+ result = result * 31 + (($forcedHosts == null) ? 0 : $forcedHosts.hashCode());
+ final Object $texturePack = this.getTexturePack();
+ result = result * 31 + (($texturePack == null) ? 0 : $texturePack.hashCode());
+ final Object $tabList = this.getTabList();
+ result = result * 31 + (($tabList == null) ? 0 : $tabList.hashCode());
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "ListenerInfo(host=" + this.getHost() + ", motd=" + this.getMotd() + ", maxPlayers=" + this.getMaxPlayers() + ", tabListSize=" + this.getTabListSize() + ", defaultServer=" + this.getDefaultServer() + ", fallbackServer="
+ + this.getFallbackServer() + ", forceDefault=" + this.isForceDefault() + ", websocket=" + this.isWebsocket() + ", forcedHosts=" + this.getForcedHosts() + ", texturePack=" + this.getTexturePack() + ", tabList=" + this.getTabList() + ")";
+ }
+
+ public boolean isWebsocket() {
+ return websocket;
+ }
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/api/config/ServerInfo.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/config/ServerInfo.java
new file mode 100644
index 0000000..98705ed
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/config/ServerInfo.java
@@ -0,0 +1,26 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.api.config;
+
+import net.md_5.bungee.api.ServerPing;
+import net.md_5.bungee.api.Callback;
+import net.md_5.bungee.api.CommandSender;
+import net.md_5.bungee.api.connection.ProxiedPlayer;
+import java.util.Collection;
+import java.net.InetSocketAddress;
+
+public interface ServerInfo {
+ String getName();
+
+ InetSocketAddress getAddress();
+
+ Collection getPlayers();
+
+ boolean canAccess(final CommandSender p0);
+
+ void sendData(final String p0, final byte[] p1);
+
+ void ping(final Callback p0);
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/api/config/TexturePackInfo.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/config/TexturePackInfo.java
new file mode 100644
index 0000000..5e8ade5
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/config/TexturePackInfo.java
@@ -0,0 +1,69 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.api.config;
+
+import java.beans.ConstructorProperties;
+
+public class TexturePackInfo {
+ private final String url;
+ private final int size;
+
+ @ConstructorProperties({ "url", "size" })
+ public TexturePackInfo(final String url, final int size) {
+ this.url = url;
+ this.size = size;
+ }
+
+ public String getUrl() {
+ return this.url;
+ }
+
+ public int getSize() {
+ return this.size;
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (o == this) {
+ return true;
+ }
+ if (!(o instanceof TexturePackInfo)) {
+ return false;
+ }
+ final TexturePackInfo other = (TexturePackInfo) o;
+ if (!other.canEqual(this)) {
+ return false;
+ }
+ final Object this$url = this.getUrl();
+ final Object other$url = other.getUrl();
+ if (this$url == null) {
+ if (other$url == null) {
+ return this.getSize() == other.getSize();
+ }
+ } else if (this$url.equals(other$url)) {
+ return this.getSize() == other.getSize();
+ }
+ return false;
+ }
+
+ public boolean canEqual(final Object other) {
+ return other instanceof TexturePackInfo;
+ }
+
+ @Override
+ public int hashCode() {
+ final int PRIME = 31;
+ int result = 1;
+ final Object $url = this.getUrl();
+ result = result * 31 + (($url == null) ? 0 : $url.hashCode());
+ result = result * 31 + this.getSize();
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "TexturePackInfo(url=" + this.getUrl() + ", size=" + this.getSize() + ")";
+ }
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/api/connection/ConnectedPlayer.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/connection/ConnectedPlayer.java
new file mode 100644
index 0000000..c4431cd
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/connection/ConnectedPlayer.java
@@ -0,0 +1,8 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.api.connection;
+
+public interface ConnectedPlayer extends ProxiedPlayer {
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/api/connection/Connection.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/connection/Connection.java
new file mode 100644
index 0000000..22fba2d
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/connection/Connection.java
@@ -0,0 +1,20 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.api.connection;
+
+import net.md_5.bungee.protocol.packet.DefinedPacket;
+import java.net.InetSocketAddress;
+
+public interface Connection {
+ InetSocketAddress getAddress();
+
+ void disconnect(final String p0);
+
+ Unsafe unsafe();
+
+ public interface Unsafe {
+ void sendPacket(final DefinedPacket p0);
+ }
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/api/connection/PendingConnection.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/connection/PendingConnection.java
new file mode 100644
index 0000000..24cbaba
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/connection/PendingConnection.java
@@ -0,0 +1,18 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.api.connection;
+
+import net.md_5.bungee.api.config.ListenerInfo;
+import java.net.InetSocketAddress;
+
+public interface PendingConnection extends Connection {
+ String getName();
+
+ byte getVersion();
+
+ InetSocketAddress getVirtualHost();
+
+ ListenerInfo getListener();
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/api/connection/ProxiedPlayer.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/connection/ProxiedPlayer.java
new file mode 100644
index 0000000..e8c35a2
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/connection/ProxiedPlayer.java
@@ -0,0 +1,34 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.api.connection;
+
+import net.md_5.bungee.api.tab.TabListHandler;
+import net.md_5.bungee.api.config.TexturePackInfo;
+import net.md_5.bungee.api.config.ServerInfo;
+import net.md_5.bungee.api.CommandSender;
+
+public interface ProxiedPlayer extends Connection, CommandSender {
+ String getDisplayName();
+
+ void setDisplayName(final String p0);
+
+ void connect(final ServerInfo p0);
+
+ Server getServer();
+
+ int getPing();
+
+ void sendData(final String p0, final byte[] p1);
+
+ PendingConnection getPendingConnection();
+
+ void chat(final String p0);
+
+ void setTexturePack(final TexturePackInfo p0);
+
+ void setTabList(final TabListHandler p0);
+
+ TabListHandler getTabList();
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/api/connection/Server.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/connection/Server.java
new file mode 100644
index 0000000..ee6b394
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/connection/Server.java
@@ -0,0 +1,13 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.api.connection;
+
+import net.md_5.bungee.api.config.ServerInfo;
+
+public interface Server extends Connection {
+ ServerInfo getInfo();
+
+ void sendData(final String p0, final byte[] p1);
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/api/event/AsyncEvent.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/event/AsyncEvent.java
new file mode 100644
index 0000000..0d15d10
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/event/AsyncEvent.java
@@ -0,0 +1,159 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.api.event;
+
+import java.beans.ConstructorProperties;
+import java.util.Map;
+import java.util.Collections;
+import java.util.concurrent.ConcurrentHashMap;
+import com.google.common.base.Preconditions;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicBoolean;
+import net.md_5.bungee.api.plugin.Plugin;
+import java.util.Set;
+import net.md_5.bungee.api.Callback;
+import net.md_5.bungee.api.plugin.Event;
+
+public class AsyncEvent extends Event {
+ private final Callback done;
+ private final Set intents;
+ private final AtomicBoolean fired;
+ private final AtomicInteger latch;
+
+ @Override
+ public void postCall() {
+ this.fired.set(true);
+ if (this.latch.get() == 0) {
+ this.done.done((T) this, null);
+ }
+ }
+
+ public void registerIntent(final Plugin plugin) {
+ Preconditions.checkState(!this.fired.get(), "Event %s has already been fired", new Object[] { this });
+ Preconditions.checkState(!this.intents.contains(plugin), "Plugin %s already registered intent for event %s", new Object[] { plugin, this });
+ this.intents.add(plugin);
+ this.latch.incrementAndGet();
+ }
+
+ public void completeIntent(final Plugin plugin) {
+ Preconditions.checkState(this.intents.contains(plugin), "Plugin %s has not registered intent for event %s", new Object[] { plugin, this });
+ this.intents.remove(plugin);
+ if (this.latch.decrementAndGet() == 0 && this.fired.get()) {
+ this.done.done((T) this, null);
+ }
+ }
+
+ @ConstructorProperties({ "done" })
+ public AsyncEvent(final Callback done) {
+ this.intents = Collections.newSetFromMap(new ConcurrentHashMap());
+ this.fired = new AtomicBoolean();
+ this.latch = new AtomicInteger();
+ this.done = done;
+ }
+
+ public Callback getDone() {
+ return this.done;
+ }
+
+ public Set getIntents() {
+ return this.intents;
+ }
+
+ public AtomicBoolean getFired() {
+ return this.fired;
+ }
+
+ public AtomicInteger getLatch() {
+ return this.latch;
+ }
+
+ @Override
+ public String toString() {
+ return "AsyncEvent(super=" + super.toString() + ", done=" + this.getDone() + ", intents=" + this.getIntents() + ", fired=" + this.getFired() + ", latch=" + this.getLatch() + ")";
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (o == this) {
+ return true;
+ }
+ if (!(o instanceof AsyncEvent)) {
+ return false;
+ }
+ final AsyncEvent> other = (AsyncEvent>) o;
+ if (!other.canEqual(this)) {
+ return false;
+ }
+ if (!super.equals(o)) {
+ return false;
+ }
+ final Object this$done = this.getDone();
+ final Object other$done = other.getDone();
+ Label_0075: {
+ if (this$done == null) {
+ if (other$done == null) {
+ break Label_0075;
+ }
+ } else if (this$done.equals(other$done)) {
+ break Label_0075;
+ }
+ return false;
+ }
+ final Object this$intents = this.getIntents();
+ final Object other$intents = other.getIntents();
+ Label_0112: {
+ if (this$intents == null) {
+ if (other$intents == null) {
+ break Label_0112;
+ }
+ } else if (this$intents.equals(other$intents)) {
+ break Label_0112;
+ }
+ return false;
+ }
+ final Object this$fired = this.getFired();
+ final Object other$fired = other.getFired();
+ Label_0149: {
+ if (this$fired == null) {
+ if (other$fired == null) {
+ break Label_0149;
+ }
+ } else if (this$fired.equals(other$fired)) {
+ break Label_0149;
+ }
+ return false;
+ }
+ final Object this$latch = this.getLatch();
+ final Object other$latch = other.getLatch();
+ if (this$latch == null) {
+ if (other$latch == null) {
+ return true;
+ }
+ } else if (this$latch.equals(other$latch)) {
+ return true;
+ }
+ return false;
+ }
+
+ public boolean canEqual(final Object other) {
+ return other instanceof AsyncEvent;
+ }
+
+ @Override
+ public int hashCode() {
+ final int PRIME = 31;
+ int result = 1;
+ result = result * 31 + super.hashCode();
+ final Object $done = this.getDone();
+ result = result * 31 + (($done == null) ? 0 : $done.hashCode());
+ final Object $intents = this.getIntents();
+ result = result * 31 + (($intents == null) ? 0 : $intents.hashCode());
+ final Object $fired = this.getFired();
+ result = result * 31 + (($fired == null) ? 0 : $fired.hashCode());
+ final Object $latch = this.getLatch();
+ result = result * 31 + (($latch == null) ? 0 : $latch.hashCode());
+ return result;
+ }
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/api/event/ChatEvent.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/event/ChatEvent.java
new file mode 100644
index 0000000..f8b2d96
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/event/ChatEvent.java
@@ -0,0 +1,91 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.api.event;
+
+import net.md_5.bungee.api.connection.Connection;
+import net.md_5.bungee.api.plugin.Cancellable;
+
+public class ChatEvent extends TargetedEvent implements Cancellable {
+ private boolean cancelled;
+ private String message;
+
+ public ChatEvent(final Connection sender, final Connection receiver, final String message) {
+ super(sender, receiver);
+ this.message = message;
+ }
+
+ public boolean isCommand() {
+ return this.message.length() > 0 && this.message.charAt(0) == '/';
+ }
+
+ @Override
+ public boolean isCancelled() {
+ return this.cancelled;
+ }
+
+ public String getMessage() {
+ return this.message;
+ }
+
+ @Override
+ public void setCancelled(final boolean cancelled) {
+ this.cancelled = cancelled;
+ }
+
+ public void setMessage(final String message) {
+ this.message = message;
+ }
+
+ @Override
+ public String toString() {
+ return "ChatEvent(super=" + super.toString() + ", cancelled=" + this.isCancelled() + ", message=" + this.getMessage() + ")";
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (o == this) {
+ return true;
+ }
+ if (!(o instanceof ChatEvent)) {
+ return false;
+ }
+ final ChatEvent other = (ChatEvent) o;
+ if (!other.canEqual(this)) {
+ return false;
+ }
+ if (!super.equals(o)) {
+ return false;
+ }
+ if (this.isCancelled() != other.isCancelled()) {
+ return false;
+ }
+ final Object this$message = this.getMessage();
+ final Object other$message = other.getMessage();
+ if (this$message == null) {
+ if (other$message == null) {
+ return true;
+ }
+ } else if (this$message.equals(other$message)) {
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean canEqual(final Object other) {
+ return other instanceof ChatEvent;
+ }
+
+ @Override
+ public int hashCode() {
+ final int PRIME = 31;
+ int result = 1;
+ result = result * 31 + super.hashCode();
+ result = result * 31 + (this.isCancelled() ? 1231 : 1237);
+ final Object $message = this.getMessage();
+ result = result * 31 + (($message == null) ? 0 : $message.hashCode());
+ return result;
+ }
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/api/event/LoginEvent.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/event/LoginEvent.java
new file mode 100644
index 0000000..7fa2aa5
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/event/LoginEvent.java
@@ -0,0 +1,103 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.api.event;
+
+import net.md_5.bungee.api.Callback;
+import net.md_5.bungee.api.connection.PendingConnection;
+import net.md_5.bungee.api.plugin.Cancellable;
+
+public class LoginEvent extends AsyncEvent implements Cancellable {
+ private boolean cancelled;
+ private String cancelReason;
+ private final PendingConnection connection;
+
+ public LoginEvent(final PendingConnection connection, final Callback done) {
+ super(done);
+ this.connection = connection;
+ }
+
+ @Override
+ public boolean isCancelled() {
+ return this.cancelled;
+ }
+
+ public String getCancelReason() {
+ return this.cancelReason;
+ }
+
+ public PendingConnection getConnection() {
+ return this.connection;
+ }
+
+ @Override
+ public void setCancelled(final boolean cancelled) {
+ this.cancelled = cancelled;
+ }
+
+ public void setCancelReason(final String cancelReason) {
+ this.cancelReason = cancelReason;
+ }
+
+ @Override
+ public String toString() {
+ return "LoginEvent(cancelled=" + this.isCancelled() + ", cancelReason=" + this.getCancelReason() + ", connection=" + this.getConnection() + ")";
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (o == this) {
+ return true;
+ }
+ if (!(o instanceof LoginEvent)) {
+ return false;
+ }
+ final LoginEvent other = (LoginEvent) o;
+ if (!other.canEqual(this)) {
+ return false;
+ }
+ if (this.isCancelled() != other.isCancelled()) {
+ return false;
+ }
+ final Object this$cancelReason = this.getCancelReason();
+ final Object other$cancelReason = other.getCancelReason();
+ Label_0078: {
+ if (this$cancelReason == null) {
+ if (other$cancelReason == null) {
+ break Label_0078;
+ }
+ } else if (this$cancelReason.equals(other$cancelReason)) {
+ break Label_0078;
+ }
+ return false;
+ }
+ final Object this$connection = this.getConnection();
+ final Object other$connection = other.getConnection();
+ if (this$connection == null) {
+ if (other$connection == null) {
+ return true;
+ }
+ } else if (this$connection.equals(other$connection)) {
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean canEqual(final Object other) {
+ return other instanceof LoginEvent;
+ }
+
+ @Override
+ public int hashCode() {
+ final int PRIME = 31;
+ int result = 1;
+ result = result * 31 + (this.isCancelled() ? 1231 : 1237);
+ final Object $cancelReason = this.getCancelReason();
+ result = result * 31 + (($cancelReason == null) ? 0 : $cancelReason.hashCode());
+ final Object $connection = this.getConnection();
+ result = result * 31 + (($connection == null) ? 0 : $connection.hashCode());
+ return result;
+ }
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/api/event/PermissionCheckEvent.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/event/PermissionCheckEvent.java
new file mode 100644
index 0000000..2fb3c95
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/event/PermissionCheckEvent.java
@@ -0,0 +1,95 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.api.event;
+
+import java.beans.ConstructorProperties;
+import net.md_5.bungee.api.CommandSender;
+import net.md_5.bungee.api.plugin.Event;
+
+public class PermissionCheckEvent extends Event {
+ private final CommandSender sender;
+ private final String permission;
+ private boolean hasPermission;
+
+ public boolean hasPermission() {
+ return this.hasPermission;
+ }
+
+ public CommandSender getSender() {
+ return this.sender;
+ }
+
+ public String getPermission() {
+ return this.permission;
+ }
+
+ public void setHasPermission(final boolean hasPermission) {
+ this.hasPermission = hasPermission;
+ }
+
+ @ConstructorProperties({ "sender", "permission", "hasPermission" })
+ public PermissionCheckEvent(final CommandSender sender, final String permission, final boolean hasPermission) {
+ this.sender = sender;
+ this.permission = permission;
+ this.hasPermission = hasPermission;
+ }
+
+ @Override
+ public String toString() {
+ return "PermissionCheckEvent(sender=" + this.getSender() + ", permission=" + this.getPermission() + ", hasPermission=" + this.hasPermission + ")";
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (o == this) {
+ return true;
+ }
+ if (!(o instanceof PermissionCheckEvent)) {
+ return false;
+ }
+ final PermissionCheckEvent other = (PermissionCheckEvent) o;
+ if (!other.canEqual(this)) {
+ return false;
+ }
+ final Object this$sender = this.getSender();
+ final Object other$sender = other.getSender();
+ Label_0065: {
+ if (this$sender == null) {
+ if (other$sender == null) {
+ break Label_0065;
+ }
+ } else if (this$sender.equals(other$sender)) {
+ break Label_0065;
+ }
+ return false;
+ }
+ final Object this$permission = this.getPermission();
+ final Object other$permission = other.getPermission();
+ if (this$permission == null) {
+ if (other$permission == null) {
+ return this.hasPermission == other.hasPermission;
+ }
+ } else if (this$permission.equals(other$permission)) {
+ return this.hasPermission == other.hasPermission;
+ }
+ return false;
+ }
+
+ public boolean canEqual(final Object other) {
+ return other instanceof PermissionCheckEvent;
+ }
+
+ @Override
+ public int hashCode() {
+ final int PRIME = 31;
+ int result = 1;
+ final Object $sender = this.getSender();
+ result = result * 31 + (($sender == null) ? 0 : $sender.hashCode());
+ final Object $permission = this.getPermission();
+ result = result * 31 + (($permission == null) ? 0 : $permission.hashCode());
+ result = result * 31 + (this.hasPermission ? 1231 : 1237);
+ return result;
+ }
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/api/event/PlayerDisconnectEvent.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/event/PlayerDisconnectEvent.java
new file mode 100644
index 0000000..e0d9e5d
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/event/PlayerDisconnectEvent.java
@@ -0,0 +1,64 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.api.event;
+
+import java.beans.ConstructorProperties;
+import net.md_5.bungee.api.connection.ProxiedPlayer;
+import net.md_5.bungee.api.plugin.Event;
+
+public class PlayerDisconnectEvent extends Event {
+ private final ProxiedPlayer player;
+
+ @ConstructorProperties({ "player" })
+ public PlayerDisconnectEvent(final ProxiedPlayer player) {
+ this.player = player;
+ }
+
+ public ProxiedPlayer getPlayer() {
+ return this.player;
+ }
+
+ @Override
+ public String toString() {
+ return "PlayerDisconnectEvent(player=" + this.getPlayer() + ")";
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (o == this) {
+ return true;
+ }
+ if (!(o instanceof PlayerDisconnectEvent)) {
+ return false;
+ }
+ final PlayerDisconnectEvent other = (PlayerDisconnectEvent) o;
+ if (!other.canEqual(this)) {
+ return false;
+ }
+ final Object this$player = this.getPlayer();
+ final Object other$player = other.getPlayer();
+ if (this$player == null) {
+ if (other$player == null) {
+ return true;
+ }
+ } else if (this$player.equals(other$player)) {
+ return true;
+ }
+ return false;
+ }
+
+ public boolean canEqual(final Object other) {
+ return other instanceof PlayerDisconnectEvent;
+ }
+
+ @Override
+ public int hashCode() {
+ final int PRIME = 31;
+ int result = 1;
+ final Object $player = this.getPlayer();
+ result = result * 31 + (($player == null) ? 0 : $player.hashCode());
+ return result;
+ }
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/api/event/PluginMessageEvent.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/event/PluginMessageEvent.java
new file mode 100644
index 0000000..58f75a5
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/event/PluginMessageEvent.java
@@ -0,0 +1,91 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.api.event;
+
+import java.util.Arrays;
+import net.md_5.bungee.api.connection.Connection;
+import net.md_5.bungee.api.plugin.Cancellable;
+
+public class PluginMessageEvent extends TargetedEvent implements Cancellable {
+ private boolean cancelled;
+ private final String tag;
+ private final byte[] data;
+
+ public PluginMessageEvent(final Connection sender, final Connection receiver, final String tag, final byte[] data) {
+ super(sender, receiver);
+ this.tag = tag;
+ this.data = data;
+ }
+
+ @Override
+ public boolean isCancelled() {
+ return this.cancelled;
+ }
+
+ public String getTag() {
+ return this.tag;
+ }
+
+ public byte[] getData() {
+ return this.data;
+ }
+
+ @Override
+ public void setCancelled(final boolean cancelled) {
+ this.cancelled = cancelled;
+ }
+
+ @Override
+ public String toString() {
+ return "PluginMessageEvent(super=" + super.toString() + ", cancelled=" + this.isCancelled() + ", tag=" + this.getTag() + ", data=" + Arrays.toString(this.getData()) + ")";
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (o == this) {
+ return true;
+ }
+ if (!(o instanceof PluginMessageEvent)) {
+ return false;
+ }
+ final PluginMessageEvent other = (PluginMessageEvent) o;
+ if (!other.canEqual(this)) {
+ return false;
+ }
+ if (!super.equals(o)) {
+ return false;
+ }
+ if (this.isCancelled() != other.isCancelled()) {
+ return false;
+ }
+ final Object this$tag = this.getTag();
+ final Object other$tag = other.getTag();
+ if (this$tag == null) {
+ if (other$tag == null) {
+ return Arrays.equals(this.getData(), other.getData());
+ }
+ } else if (this$tag.equals(other$tag)) {
+ return Arrays.equals(this.getData(), other.getData());
+ }
+ return false;
+ }
+
+ @Override
+ public boolean canEqual(final Object other) {
+ return other instanceof PluginMessageEvent;
+ }
+
+ @Override
+ public int hashCode() {
+ final int PRIME = 31;
+ int result = 1;
+ result = result * 31 + super.hashCode();
+ result = result * 31 + (this.isCancelled() ? 1231 : 1237);
+ final Object $tag = this.getTag();
+ result = result * 31 + (($tag == null) ? 0 : $tag.hashCode());
+ result = result * 31 + Arrays.hashCode(this.getData());
+ return result;
+ }
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/api/event/PostLoginEvent.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/event/PostLoginEvent.java
new file mode 100644
index 0000000..d5aa89a
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/event/PostLoginEvent.java
@@ -0,0 +1,64 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.api.event;
+
+import java.beans.ConstructorProperties;
+import net.md_5.bungee.api.connection.ProxiedPlayer;
+import net.md_5.bungee.api.plugin.Event;
+
+public class PostLoginEvent extends Event {
+ private final ProxiedPlayer player;
+
+ @ConstructorProperties({ "player" })
+ public PostLoginEvent(final ProxiedPlayer player) {
+ this.player = player;
+ }
+
+ public ProxiedPlayer getPlayer() {
+ return this.player;
+ }
+
+ @Override
+ public String toString() {
+ return "PostLoginEvent(player=" + this.getPlayer() + ")";
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (o == this) {
+ return true;
+ }
+ if (!(o instanceof PostLoginEvent)) {
+ return false;
+ }
+ final PostLoginEvent other = (PostLoginEvent) o;
+ if (!other.canEqual(this)) {
+ return false;
+ }
+ final Object this$player = this.getPlayer();
+ final Object other$player = other.getPlayer();
+ if (this$player == null) {
+ if (other$player == null) {
+ return true;
+ }
+ } else if (this$player.equals(other$player)) {
+ return true;
+ }
+ return false;
+ }
+
+ public boolean canEqual(final Object other) {
+ return other instanceof PostLoginEvent;
+ }
+
+ @Override
+ public int hashCode() {
+ final int PRIME = 31;
+ int result = 1;
+ final Object $player = this.getPlayer();
+ result = result * 31 + (($player == null) ? 0 : $player.hashCode());
+ return result;
+ }
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/api/event/ProxyPingEvent.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/event/ProxyPingEvent.java
new file mode 100644
index 0000000..aaeb85a
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/event/ProxyPingEvent.java
@@ -0,0 +1,89 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.api.event;
+
+import java.beans.ConstructorProperties;
+import net.md_5.bungee.api.ServerPing;
+import net.md_5.bungee.api.connection.PendingConnection;
+import net.md_5.bungee.api.plugin.Event;
+
+public class ProxyPingEvent extends Event {
+ private final PendingConnection connection;
+ private ServerPing response;
+
+ public PendingConnection getConnection() {
+ return this.connection;
+ }
+
+ public ServerPing getResponse() {
+ return this.response;
+ }
+
+ public void setResponse(final ServerPing response) {
+ this.response = response;
+ }
+
+ @ConstructorProperties({ "connection", "response" })
+ public ProxyPingEvent(final PendingConnection connection, final ServerPing response) {
+ this.connection = connection;
+ this.response = response;
+ }
+
+ @Override
+ public String toString() {
+ return "ProxyPingEvent(connection=" + this.getConnection() + ", response=" + this.getResponse() + ")";
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (o == this) {
+ return true;
+ }
+ if (!(o instanceof ProxyPingEvent)) {
+ return false;
+ }
+ final ProxyPingEvent other = (ProxyPingEvent) o;
+ if (!other.canEqual(this)) {
+ return false;
+ }
+ final Object this$connection = this.getConnection();
+ final Object other$connection = other.getConnection();
+ Label_0065: {
+ if (this$connection == null) {
+ if (other$connection == null) {
+ break Label_0065;
+ }
+ } else if (this$connection.equals(other$connection)) {
+ break Label_0065;
+ }
+ return false;
+ }
+ final Object this$response = this.getResponse();
+ final Object other$response = other.getResponse();
+ if (this$response == null) {
+ if (other$response == null) {
+ return true;
+ }
+ } else if (this$response.equals(other$response)) {
+ return true;
+ }
+ return false;
+ }
+
+ public boolean canEqual(final Object other) {
+ return other instanceof ProxyPingEvent;
+ }
+
+ @Override
+ public int hashCode() {
+ final int PRIME = 31;
+ int result = 1;
+ final Object $connection = this.getConnection();
+ result = result * 31 + (($connection == null) ? 0 : $connection.hashCode());
+ final Object $response = this.getResponse();
+ result = result * 31 + (($response == null) ? 0 : $response.hashCode());
+ return result;
+ }
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/api/event/ServerConnectEvent.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/event/ServerConnectEvent.java
new file mode 100644
index 0000000..3fafc25
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/event/ServerConnectEvent.java
@@ -0,0 +1,100 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.api.event;
+
+import net.md_5.bungee.api.config.ServerInfo;
+import net.md_5.bungee.api.connection.ProxiedPlayer;
+import net.md_5.bungee.api.plugin.Cancellable;
+import net.md_5.bungee.api.plugin.Event;
+
+public class ServerConnectEvent extends Event implements Cancellable {
+ private final ProxiedPlayer player;
+ private ServerInfo target;
+ private boolean cancelled;
+
+ public ServerConnectEvent(final ProxiedPlayer player, final ServerInfo target) {
+ this.player = player;
+ this.target = target;
+ }
+
+ public ProxiedPlayer getPlayer() {
+ return this.player;
+ }
+
+ public ServerInfo getTarget() {
+ return this.target;
+ }
+
+ @Override
+ public boolean isCancelled() {
+ return this.cancelled;
+ }
+
+ public void setTarget(final ServerInfo target) {
+ this.target = target;
+ }
+
+ @Override
+ public void setCancelled(final boolean cancelled) {
+ this.cancelled = cancelled;
+ }
+
+ @Override
+ public String toString() {
+ return "ServerConnectEvent(player=" + this.getPlayer() + ", target=" + this.getTarget() + ", cancelled=" + this.isCancelled() + ")";
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (o == this) {
+ return true;
+ }
+ if (!(o instanceof ServerConnectEvent)) {
+ return false;
+ }
+ final ServerConnectEvent other = (ServerConnectEvent) o;
+ if (!other.canEqual(this)) {
+ return false;
+ }
+ final Object this$player = this.getPlayer();
+ final Object other$player = other.getPlayer();
+ Label_0065: {
+ if (this$player == null) {
+ if (other$player == null) {
+ break Label_0065;
+ }
+ } else if (this$player.equals(other$player)) {
+ break Label_0065;
+ }
+ return false;
+ }
+ final Object this$target = this.getTarget();
+ final Object other$target = other.getTarget();
+ if (this$target == null) {
+ if (other$target == null) {
+ return this.isCancelled() == other.isCancelled();
+ }
+ } else if (this$target.equals(other$target)) {
+ return this.isCancelled() == other.isCancelled();
+ }
+ return false;
+ }
+
+ public boolean canEqual(final Object other) {
+ return other instanceof ServerConnectEvent;
+ }
+
+ @Override
+ public int hashCode() {
+ final int PRIME = 31;
+ int result = 1;
+ final Object $player = this.getPlayer();
+ result = result * 31 + (($player == null) ? 0 : $player.hashCode());
+ final Object $target = this.getTarget();
+ result = result * 31 + (($target == null) ? 0 : $target.hashCode());
+ result = result * 31 + (this.isCancelled() ? 1231 : 1237);
+ return result;
+ }
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/api/event/ServerConnectedEvent.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/event/ServerConnectedEvent.java
new file mode 100644
index 0000000..1a337ba
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/event/ServerConnectedEvent.java
@@ -0,0 +1,85 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.api.event;
+
+import java.beans.ConstructorProperties;
+import net.md_5.bungee.api.connection.Server;
+import net.md_5.bungee.api.connection.ProxiedPlayer;
+import net.md_5.bungee.api.plugin.Event;
+
+public class ServerConnectedEvent extends Event {
+ private final ProxiedPlayer player;
+ private final Server server;
+
+ @ConstructorProperties({ "player", "server" })
+ public ServerConnectedEvent(final ProxiedPlayer player, final Server server) {
+ this.player = player;
+ this.server = server;
+ }
+
+ public ProxiedPlayer getPlayer() {
+ return this.player;
+ }
+
+ public Server getServer() {
+ return this.server;
+ }
+
+ @Override
+ public String toString() {
+ return "ServerConnectedEvent(player=" + this.getPlayer() + ", server=" + this.getServer() + ")";
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (o == this) {
+ return true;
+ }
+ if (!(o instanceof ServerConnectedEvent)) {
+ return false;
+ }
+ final ServerConnectedEvent other = (ServerConnectedEvent) o;
+ if (!other.canEqual(this)) {
+ return false;
+ }
+ final Object this$player = this.getPlayer();
+ final Object other$player = other.getPlayer();
+ Label_0065: {
+ if (this$player == null) {
+ if (other$player == null) {
+ break Label_0065;
+ }
+ } else if (this$player.equals(other$player)) {
+ break Label_0065;
+ }
+ return false;
+ }
+ final Object this$server = this.getServer();
+ final Object other$server = other.getServer();
+ if (this$server == null) {
+ if (other$server == null) {
+ return true;
+ }
+ } else if (this$server.equals(other$server)) {
+ return true;
+ }
+ return false;
+ }
+
+ public boolean canEqual(final Object other) {
+ return other instanceof ServerConnectedEvent;
+ }
+
+ @Override
+ public int hashCode() {
+ final int PRIME = 31;
+ int result = 1;
+ final Object $player = this.getPlayer();
+ result = result * 31 + (($player == null) ? 0 : $player.hashCode());
+ final Object $server = this.getServer();
+ result = result * 31 + (($server == null) ? 0 : $server.hashCode());
+ return result;
+ }
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/api/event/ServerKickEvent.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/event/ServerKickEvent.java
new file mode 100644
index 0000000..044f385
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/event/ServerKickEvent.java
@@ -0,0 +1,127 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.api.event;
+
+import net.md_5.bungee.api.config.ServerInfo;
+import net.md_5.bungee.api.connection.ProxiedPlayer;
+import net.md_5.bungee.api.plugin.Cancellable;
+import net.md_5.bungee.api.plugin.Event;
+
+public class ServerKickEvent extends Event implements Cancellable {
+ private boolean cancelled;
+ private final ProxiedPlayer player;
+ private String kickReason;
+ private ServerInfo cancelServer;
+
+ public ServerKickEvent(final ProxiedPlayer player, final String kickReason, final ServerInfo cancelServer) {
+ this.player = player;
+ this.kickReason = kickReason;
+ this.cancelServer = cancelServer;
+ }
+
+ @Override
+ public boolean isCancelled() {
+ return this.cancelled;
+ }
+
+ public ProxiedPlayer getPlayer() {
+ return this.player;
+ }
+
+ public String getKickReason() {
+ return this.kickReason;
+ }
+
+ public ServerInfo getCancelServer() {
+ return this.cancelServer;
+ }
+
+ @Override
+ public void setCancelled(final boolean cancelled) {
+ this.cancelled = cancelled;
+ }
+
+ public void setKickReason(final String kickReason) {
+ this.kickReason = kickReason;
+ }
+
+ public void setCancelServer(final ServerInfo cancelServer) {
+ this.cancelServer = cancelServer;
+ }
+
+ @Override
+ public String toString() {
+ return "ServerKickEvent(cancelled=" + this.isCancelled() + ", player=" + this.getPlayer() + ", kickReason=" + this.getKickReason() + ", cancelServer=" + this.getCancelServer() + ")";
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (o == this) {
+ return true;
+ }
+ if (!(o instanceof ServerKickEvent)) {
+ return false;
+ }
+ final ServerKickEvent other = (ServerKickEvent) o;
+ if (!other.canEqual(this)) {
+ return false;
+ }
+ if (this.isCancelled() != other.isCancelled()) {
+ return false;
+ }
+ final Object this$player = this.getPlayer();
+ final Object other$player = other.getPlayer();
+ Label_0078: {
+ if (this$player == null) {
+ if (other$player == null) {
+ break Label_0078;
+ }
+ } else if (this$player.equals(other$player)) {
+ break Label_0078;
+ }
+ return false;
+ }
+ final Object this$kickReason = this.getKickReason();
+ final Object other$kickReason = other.getKickReason();
+ Label_0115: {
+ if (this$kickReason == null) {
+ if (other$kickReason == null) {
+ break Label_0115;
+ }
+ } else if (this$kickReason.equals(other$kickReason)) {
+ break Label_0115;
+ }
+ return false;
+ }
+ final Object this$cancelServer = this.getCancelServer();
+ final Object other$cancelServer = other.getCancelServer();
+ if (this$cancelServer == null) {
+ if (other$cancelServer == null) {
+ return true;
+ }
+ } else if (this$cancelServer.equals(other$cancelServer)) {
+ return true;
+ }
+ return false;
+ }
+
+ public boolean canEqual(final Object other) {
+ return other instanceof ServerKickEvent;
+ }
+
+ @Override
+ public int hashCode() {
+ final int PRIME = 31;
+ int result = 1;
+ result = result * 31 + (this.isCancelled() ? 1231 : 1237);
+ final Object $player = this.getPlayer();
+ result = result * 31 + (($player == null) ? 0 : $player.hashCode());
+ final Object $kickReason = this.getKickReason();
+ result = result * 31 + (($kickReason == null) ? 0 : $kickReason.hashCode());
+ final Object $cancelServer = this.getCancelServer();
+ result = result * 31 + (($cancelServer == null) ? 0 : $cancelServer.hashCode());
+ return result;
+ }
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/api/event/ServerSwitchEvent.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/event/ServerSwitchEvent.java
new file mode 100644
index 0000000..943a275
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/event/ServerSwitchEvent.java
@@ -0,0 +1,64 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.api.event;
+
+import java.beans.ConstructorProperties;
+import net.md_5.bungee.api.connection.ProxiedPlayer;
+import net.md_5.bungee.api.plugin.Event;
+
+public class ServerSwitchEvent extends Event {
+ private final ProxiedPlayer player;
+
+ @ConstructorProperties({ "player" })
+ public ServerSwitchEvent(final ProxiedPlayer player) {
+ this.player = player;
+ }
+
+ public ProxiedPlayer getPlayer() {
+ return this.player;
+ }
+
+ @Override
+ public String toString() {
+ return "ServerSwitchEvent(player=" + this.getPlayer() + ")";
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (o == this) {
+ return true;
+ }
+ if (!(o instanceof ServerSwitchEvent)) {
+ return false;
+ }
+ final ServerSwitchEvent other = (ServerSwitchEvent) o;
+ if (!other.canEqual(this)) {
+ return false;
+ }
+ final Object this$player = this.getPlayer();
+ final Object other$player = other.getPlayer();
+ if (this$player == null) {
+ if (other$player == null) {
+ return true;
+ }
+ } else if (this$player.equals(other$player)) {
+ return true;
+ }
+ return false;
+ }
+
+ public boolean canEqual(final Object other) {
+ return other instanceof ServerSwitchEvent;
+ }
+
+ @Override
+ public int hashCode() {
+ final int PRIME = 31;
+ int result = 1;
+ final Object $player = this.getPlayer();
+ result = result * 31 + (($player == null) ? 0 : $player.hashCode());
+ return result;
+ }
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/api/event/TargetedEvent.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/event/TargetedEvent.java
new file mode 100644
index 0000000..deba907
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/event/TargetedEvent.java
@@ -0,0 +1,84 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.api.event;
+
+import java.beans.ConstructorProperties;
+import net.md_5.bungee.api.connection.Connection;
+import net.md_5.bungee.api.plugin.Event;
+
+public abstract class TargetedEvent extends Event {
+ private final Connection sender;
+ private final Connection receiver;
+
+ public Connection getSender() {
+ return this.sender;
+ }
+
+ public Connection getReceiver() {
+ return this.receiver;
+ }
+
+ @Override
+ public String toString() {
+ return "TargetedEvent(sender=" + this.getSender() + ", receiver=" + this.getReceiver() + ")";
+ }
+
+ @ConstructorProperties({ "sender", "receiver" })
+ public TargetedEvent(final Connection sender, final Connection receiver) {
+ this.sender = sender;
+ this.receiver = receiver;
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (o == this) {
+ return true;
+ }
+ if (!(o instanceof TargetedEvent)) {
+ return false;
+ }
+ final TargetedEvent other = (TargetedEvent) o;
+ if (!other.canEqual(this)) {
+ return false;
+ }
+ final Object this$sender = this.getSender();
+ final Object other$sender = other.getSender();
+ Label_0065: {
+ if (this$sender == null) {
+ if (other$sender == null) {
+ break Label_0065;
+ }
+ } else if (this$sender.equals(other$sender)) {
+ break Label_0065;
+ }
+ return false;
+ }
+ final Object this$receiver = this.getReceiver();
+ final Object other$receiver = other.getReceiver();
+ if (this$receiver == null) {
+ if (other$receiver == null) {
+ return true;
+ }
+ } else if (this$receiver.equals(other$receiver)) {
+ return true;
+ }
+ return false;
+ }
+
+ public boolean canEqual(final Object other) {
+ return other instanceof TargetedEvent;
+ }
+
+ @Override
+ public int hashCode() {
+ final int PRIME = 31;
+ int result = 1;
+ final Object $sender = this.getSender();
+ result = result * 31 + (($sender == null) ? 0 : $sender.hashCode());
+ final Object $receiver = this.getReceiver();
+ result = result * 31 + (($receiver == null) ? 0 : $receiver.hashCode());
+ return result;
+ }
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/api/plugin/Cancellable.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/plugin/Cancellable.java
new file mode 100644
index 0000000..7df9105
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/plugin/Cancellable.java
@@ -0,0 +1,11 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.api.plugin;
+
+public interface Cancellable {
+ boolean isCancelled();
+
+ void setCancelled(final boolean p0);
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/api/plugin/Command.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/plugin/Command.java
new file mode 100644
index 0000000..60e9314
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/plugin/Command.java
@@ -0,0 +1,97 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.api.plugin;
+
+import java.util.Arrays;
+import net.md_5.bungee.api.CommandSender;
+import com.google.common.base.Preconditions;
+
+public abstract class Command {
+ private final String name;
+ private final String permission;
+ private final String[] aliases;
+
+ public Command(final String name) {
+ this(name, null, new String[0]);
+ }
+
+ public Command(final String name, final String permission, final String... aliases) {
+ Preconditions.checkArgument(name != null, (Object) "name");
+ this.name = name;
+ this.permission = permission;
+ this.aliases = aliases;
+ }
+
+ public abstract void execute(final CommandSender p0, final String[] p1);
+
+ public String getName() {
+ return this.name;
+ }
+
+ public String getPermission() {
+ return this.permission;
+ }
+
+ public String[] getAliases() {
+ return this.aliases;
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (o == this) {
+ return true;
+ }
+ if (!(o instanceof Command)) {
+ return false;
+ }
+ final Command other = (Command) o;
+ if (!other.canEqual(this)) {
+ return false;
+ }
+ final Object this$name = this.getName();
+ final Object other$name = other.getName();
+ Label_0065: {
+ if (this$name == null) {
+ if (other$name == null) {
+ break Label_0065;
+ }
+ } else if (this$name.equals(other$name)) {
+ break Label_0065;
+ }
+ return false;
+ }
+ final Object this$permission = this.getPermission();
+ final Object other$permission = other.getPermission();
+ if (this$permission == null) {
+ if (other$permission == null) {
+ return Arrays.deepEquals(this.getAliases(), other.getAliases());
+ }
+ } else if (this$permission.equals(other$permission)) {
+ return Arrays.deepEquals(this.getAliases(), other.getAliases());
+ }
+ return false;
+ }
+
+ public boolean canEqual(final Object other) {
+ return other instanceof Command;
+ }
+
+ @Override
+ public int hashCode() {
+ final int PRIME = 31;
+ int result = 1;
+ final Object $name = this.getName();
+ result = result * 31 + (($name == null) ? 0 : $name.hashCode());
+ final Object $permission = this.getPermission();
+ result = result * 31 + (($permission == null) ? 0 : $permission.hashCode());
+ result = result * 31 + Arrays.deepHashCode(this.getAliases());
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "Command(name=" + this.getName() + ", permission=" + this.getPermission() + ", aliases=" + Arrays.deepToString(this.getAliases()) + ")";
+ }
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/api/plugin/Event.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/plugin/Event.java
new file mode 100644
index 0000000..a121fef
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/plugin/Event.java
@@ -0,0 +1,10 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.api.plugin;
+
+public abstract class Event {
+ public void postCall() {
+ }
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/api/plugin/Listener.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/plugin/Listener.java
new file mode 100644
index 0000000..1758449
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/plugin/Listener.java
@@ -0,0 +1,8 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.api.plugin;
+
+public interface Listener {
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/api/plugin/Plugin.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/plugin/Plugin.java
new file mode 100644
index 0000000..b39883a
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/plugin/Plugin.java
@@ -0,0 +1,64 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.api.plugin;
+
+import java.io.InputStream;
+import java.util.logging.Logger;
+import java.io.File;
+import net.md_5.bungee.api.ProxyServer;
+
+public class Plugin {
+ private PluginDescription description;
+ private ProxyServer proxy;
+ private File file;
+ private Logger logger;
+
+ protected Plugin() {
+ }
+
+ protected Plugin(PluginDescription forceDesc) {
+ this.description = forceDesc;
+ }
+
+ public void onLoad() {
+ }
+
+ public void onEnable() {
+ }
+
+ public void onDisable() {
+ }
+
+ public final File getDataFolder() {
+ return new File(this.getProxy().getPluginsFolder(), this.getDescription().getName());
+ }
+
+ public final InputStream getResourceAsStream(final String name) {
+ return this.getClass().getClassLoader().getResourceAsStream(name);
+ }
+
+ final void init(final ProxyServer proxy, final PluginDescription description) {
+ this.proxy = proxy;
+ this.description = (this.description == null ? description : this.description);
+ this.file = description.getFile();
+ this.logger = new PluginLogger(this);
+ }
+
+ public PluginDescription getDescription() {
+ return this.description;
+ }
+
+ public ProxyServer getProxy() {
+ return this.proxy;
+ }
+
+ public File getFile() {
+ return this.file;
+ }
+
+ public Logger getLogger() {
+ return this.logger;
+ }
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/api/plugin/PluginClassloader.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/plugin/PluginClassloader.java
new file mode 100644
index 0000000..09e74f3
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/plugin/PluginClassloader.java
@@ -0,0 +1,47 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.api.plugin;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.net.URL;
+import java.util.Set;
+import java.net.URLClassLoader;
+
+public class PluginClassloader extends URLClassLoader {
+ private static final Set allLoaders;
+
+ public PluginClassloader(final URL[] urls) {
+ super(urls);
+ PluginClassloader.allLoaders.add(this);
+ }
+
+ @Override
+ protected Class> loadClass(final String name, final boolean resolve) throws ClassNotFoundException {
+ return this.loadClass0(name, resolve, true);
+ }
+
+ private Class> loadClass0(final String name, final boolean resolve, final boolean checkOther) throws ClassNotFoundException {
+ try {
+ return super.loadClass(name, resolve);
+ } catch (ClassNotFoundException ex) {
+ if (checkOther) {
+ for (final PluginClassloader loader : PluginClassloader.allLoaders) {
+ if (loader != this) {
+ try {
+ return loader.loadClass0(name, resolve, false);
+ } catch (ClassNotFoundException ex2) {
+ }
+ }
+ }
+ }
+ throw new ClassNotFoundException(name);
+ }
+ }
+
+ static {
+ allLoaders = new HashSet();
+ }
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/api/plugin/PluginDescription.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/plugin/PluginDescription.java
new file mode 100644
index 0000000..e20949d
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/plugin/PluginDescription.java
@@ -0,0 +1,196 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.api.plugin;
+
+import java.beans.ConstructorProperties;
+import java.util.HashSet;
+import java.io.File;
+import java.util.Set;
+
+public class PluginDescription {
+ private String name;
+ private String main;
+ private String version;
+ private String author;
+ private Set depends;
+ private File file;
+
+ public String getName() {
+ return this.name;
+ }
+
+ public String getMain() {
+ return this.main;
+ }
+
+ public String getVersion() {
+ return this.version;
+ }
+
+ public String getAuthor() {
+ return this.author;
+ }
+
+ public Set getDepends() {
+ return this.depends;
+ }
+
+ public File getFile() {
+ return this.file;
+ }
+
+ public void setName(final String name) {
+ this.name = name;
+ }
+
+ public void setMain(final String main) {
+ this.main = main;
+ }
+
+ public void setVersion(final String version) {
+ this.version = version;
+ }
+
+ public void setAuthor(final String author) {
+ this.author = author;
+ }
+
+ public void setDepends(final Set depends) {
+ this.depends = depends;
+ }
+
+ public void setFile(final File file) {
+ this.file = file;
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (o == this) {
+ return true;
+ }
+ if (!(o instanceof PluginDescription)) {
+ return false;
+ }
+ final PluginDescription other = (PluginDescription) o;
+ if (!other.canEqual(this)) {
+ return false;
+ }
+ final Object this$name = this.getName();
+ final Object other$name = other.getName();
+ Label_0065: {
+ if (this$name == null) {
+ if (other$name == null) {
+ break Label_0065;
+ }
+ } else if (this$name.equals(other$name)) {
+ break Label_0065;
+ }
+ return false;
+ }
+ final Object this$main = this.getMain();
+ final Object other$main = other.getMain();
+ Label_0102: {
+ if (this$main == null) {
+ if (other$main == null) {
+ break Label_0102;
+ }
+ } else if (this$main.equals(other$main)) {
+ break Label_0102;
+ }
+ return false;
+ }
+ final Object this$version = this.getVersion();
+ final Object other$version = other.getVersion();
+ Label_0139: {
+ if (this$version == null) {
+ if (other$version == null) {
+ break Label_0139;
+ }
+ } else if (this$version.equals(other$version)) {
+ break Label_0139;
+ }
+ return false;
+ }
+ final Object this$author = this.getAuthor();
+ final Object other$author = other.getAuthor();
+ Label_0176: {
+ if (this$author == null) {
+ if (other$author == null) {
+ break Label_0176;
+ }
+ } else if (this$author.equals(other$author)) {
+ break Label_0176;
+ }
+ return false;
+ }
+ final Object this$depends = this.getDepends();
+ final Object other$depends = other.getDepends();
+ Label_0213: {
+ if (this$depends == null) {
+ if (other$depends == null) {
+ break Label_0213;
+ }
+ } else if (this$depends.equals(other$depends)) {
+ break Label_0213;
+ }
+ return false;
+ }
+ final Object this$file = this.getFile();
+ final Object other$file = other.getFile();
+ if (this$file == null) {
+ if (other$file == null) {
+ return true;
+ }
+ } else if (this$file.equals(other$file)) {
+ return true;
+ }
+ return false;
+ }
+
+ public boolean canEqual(final Object other) {
+ return other instanceof PluginDescription;
+ }
+
+ @Override
+ public int hashCode() {
+ final int PRIME = 31;
+ int result = 1;
+ final Object $name = this.getName();
+ result = result * 31 + (($name == null) ? 0 : $name.hashCode());
+ final Object $main = this.getMain();
+ result = result * 31 + (($main == null) ? 0 : $main.hashCode());
+ final Object $version = this.getVersion();
+ result = result * 31 + (($version == null) ? 0 : $version.hashCode());
+ final Object $author = this.getAuthor();
+ result = result * 31 + (($author == null) ? 0 : $author.hashCode());
+ final Object $depends = this.getDepends();
+ result = result * 31 + (($depends == null) ? 0 : $depends.hashCode());
+ final Object $file = this.getFile();
+ result = result * 31 + (($file == null) ? 0 : $file.hashCode());
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "PluginDescription(name=" + this.getName() + ", main=" + this.getMain() + ", version=" + this.getVersion() + ", author=" + this.getAuthor() + ", depends=" + this.getDepends() + ", file=" + this.getFile() + ")";
+ }
+
+ public PluginDescription() {
+ this.depends = new HashSet();
+ this.file = null;
+ }
+
+ @ConstructorProperties({ "name", "main", "version", "author", "depends", "file" })
+ public PluginDescription(final String name, final String main, final String version, final String author, final Set depends, final File file) {
+ this.depends = new HashSet();
+ this.file = null;
+ this.name = name;
+ this.main = main;
+ this.version = version;
+ this.author = author;
+ this.depends = depends;
+ this.file = file;
+ }
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/api/plugin/PluginLogger.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/plugin/PluginLogger.java
new file mode 100644
index 0000000..559e046
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/plugin/PluginLogger.java
@@ -0,0 +1,25 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.api.plugin;
+
+import java.util.logging.LogRecord;
+import net.md_5.bungee.api.ProxyServer;
+import java.util.logging.Logger;
+
+public class PluginLogger extends Logger {
+ private String pluginName;
+
+ protected PluginLogger(final Plugin plugin) {
+ super(plugin.getClass().getCanonicalName(), null);
+ this.pluginName = "[" + plugin.getDescription().getName() + "] ";
+ this.setParent(ProxyServer.getInstance().getLogger());
+ }
+
+ @Override
+ public void log(final LogRecord logRecord) {
+ logRecord.setMessage(this.pluginName + logRecord.getMessage());
+ super.log(logRecord);
+ }
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/api/plugin/PluginManager.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/plugin/PluginManager.java
new file mode 100644
index 0000000..b885e17
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/plugin/PluginManager.java
@@ -0,0 +1,222 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.api.plugin;
+
+import java.beans.ConstructorProperties;
+import java.lang.reflect.Method;
+import java.io.InputStream;
+import java.util.jar.JarEntry;
+import java.util.zip.ZipEntry;
+import java.util.jar.JarFile;
+import com.google.common.base.Preconditions;
+import java.io.File;
+import java.net.URLClassLoader;
+import java.net.URL;
+import java.util.Iterator;
+import java.util.Stack;
+import java.util.Collection;
+import java.util.logging.Level;
+import net.md_5.bungee.api.ChatColor;
+import java.util.Arrays;
+import net.md_5.bungee.api.CommandSender;
+import java.lang.annotation.Annotation;
+import net.md_5.bungee.event.EventHandler;
+import com.google.common.eventbus.Subscribe;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import net.md_5.bungee.event.EventBus;
+import org.yaml.snakeyaml.Yaml;
+import net.md_5.bungee.api.ProxyServer;
+import java.util.regex.Pattern;
+
+public class PluginManager {
+ private static final Pattern argsSplit;
+ private final ProxyServer proxy;
+ private final Yaml yaml;
+ private final EventBus eventBus;
+ private final Map plugins;
+ private final Map commandMap;
+ private Map toLoad;
+
+ public PluginManager(final ProxyServer proxy) {
+ this.yaml = new Yaml();
+ this.plugins = new LinkedHashMap();
+ this.commandMap = new HashMap();
+ this.toLoad = new HashMap();
+ this.proxy = proxy;
+ this.eventBus = new EventBus(proxy.getLogger(), (Class extends Annotation>[]) new Class[] { Subscribe.class, EventHandler.class });
+ }
+
+ public void registerCommand(final Plugin plugin, final Command command) {
+ this.commandMap.put(command.getName().toLowerCase(), command);
+ for (final String alias : command.getAliases()) {
+ this.commandMap.put(alias.toLowerCase(), command);
+ }
+ }
+
+ public void unregisterCommand(final Command command) {
+ this.commandMap.values().remove(command);
+ }
+
+ public boolean dispatchCommand(final CommandSender sender, final String commandLine) {
+ final String[] split = PluginManager.argsSplit.split(commandLine);
+ final Command command = this.commandMap.get(split[0].toLowerCase());
+ if (command == null) {
+ return false;
+ }
+ final String permission = command.getPermission();
+ if (permission != null && !permission.isEmpty() && !sender.hasPermission(permission)) {
+ sender.sendMessage(this.proxy.getTranslation("no_permission"));
+ return true;
+ }
+ final String[] args = Arrays.copyOfRange(split, 1, split.length);
+ try {
+ command.execute(sender, args);
+ } catch (Exception ex) {
+ sender.sendMessage(ChatColor.RED + "An internal error occurred whilst executing this command, please check the console log for details.");
+ ProxyServer.getInstance().getLogger().log(Level.WARNING, "Error in dispatching command", ex);
+ }
+ return true;
+ }
+
+ public Collection getPlugins() {
+ return this.plugins.values();
+ }
+
+ public Plugin getPlugin(final String name) {
+ return this.plugins.get(name);
+ }
+
+ public void loadAndEnablePlugins() {
+ final Map pluginStatuses = new HashMap();
+ for (final Map.Entry entry : this.toLoad.entrySet()) {
+ final PluginDescription plugin = entry.getValue();
+ if (!this.enablePlugin(pluginStatuses, new Stack(), plugin)) {
+ ProxyServer.getInstance().getLogger().warning("Failed to enable " + entry.getKey());
+ }
+ }
+ this.toLoad.clear();
+ this.toLoad = null;
+ for (final Plugin plugin2 : this.plugins.values()) {
+ try {
+ plugin2.onEnable();
+ ProxyServer.getInstance().getLogger().log(Level.INFO, "Enabled plugin {0} version {1} by {2}",
+ new Object[] { plugin2.getDescription().getName(), plugin2.getDescription().getVersion(), plugin2.getDescription().getAuthor() });
+ } catch (Throwable t) {
+ ProxyServer.getInstance().getLogger().log(Level.WARNING, "Exception encountered when loading plugin: " + plugin2.getDescription().getName(), t);
+ }
+ }
+ }
+
+ private boolean enablePlugin(final Map pluginStatuses, final Stack dependStack, final PluginDescription plugin) {
+ if (pluginStatuses.containsKey(plugin)) {
+ return pluginStatuses.get(plugin);
+ }
+ boolean status = true;
+ for (final String dependName : plugin.getDepends()) {
+ final PluginDescription depend = this.toLoad.get(dependName);
+ Boolean dependStatus = (depend != null) ? pluginStatuses.get(depend) : Boolean.FALSE;
+ if (dependStatus == null) {
+ if (dependStack.contains(depend)) {
+ final StringBuilder dependencyGraph = new StringBuilder();
+ for (final PluginDescription element : dependStack) {
+ dependencyGraph.append(element.getName()).append(" -> ");
+ }
+ dependencyGraph.append(plugin.getName()).append(" -> ").append(dependName);
+ ProxyServer.getInstance().getLogger().log(Level.WARNING, "Circular dependency detected: " + (Object) dependencyGraph);
+ status = false;
+ } else {
+ dependStack.push(plugin);
+ dependStatus = this.enablePlugin(pluginStatuses, dependStack, depend);
+ dependStack.pop();
+ }
+ }
+ if (dependStatus == Boolean.FALSE) {
+ ProxyServer.getInstance().getLogger().log(Level.WARNING, "{0} (required by {1}) is unavailable", new Object[] { depend.getName(), plugin.getName() });
+ status = false;
+ }
+ if (!status) {
+ break;
+ }
+ }
+ if (status) {
+ try {
+ final URLClassLoader loader = new PluginClassloader(new URL[] { plugin.getFile().toURI().toURL() });
+ final Class> main = loader.loadClass(plugin.getMain());
+ final Plugin clazz = (Plugin) main.getDeclaredConstructor((Class>[]) new Class[0]).newInstance(new Object[0]);
+ clazz.init(this.proxy, plugin);
+ this.plugins.put(plugin.getName(), clazz);
+ clazz.onLoad();
+ ProxyServer.getInstance().getLogger().log(Level.INFO, "Loaded plugin {0} version {1} by {2}", new Object[] { plugin.getName(), plugin.getVersion(), plugin.getAuthor() });
+ } catch (Throwable t) {
+ this.proxy.getLogger().log(Level.WARNING, "Error enabling plugin " + plugin.getName(), t);
+ }
+ }
+ pluginStatuses.put(plugin, status);
+ return status;
+ }
+
+ public void addInternalPlugin(Plugin plug) {
+ this.plugins.put(plug.getDescription().getName(), plug);
+ plug.init(proxy, plug.getDescription());
+ }
+
+ public void detectPlugins(final File folder) {
+ Preconditions.checkNotNull((Object) folder, (Object) "folder");
+ Preconditions.checkArgument(folder.isDirectory(), (Object) "Must load from a directory");
+ for (final File file : folder.listFiles()) {
+ if (file.isFile() && file.getName().endsWith(".jar")) {
+ try (final JarFile jar = new JarFile(file)) {
+ final JarEntry pdf = jar.getJarEntry("plugin.yml");
+ Preconditions.checkNotNull((Object) pdf, (Object) "Plugin must have a plugin.yml");
+ try (final InputStream in = jar.getInputStream(pdf)) {
+ final PluginDescription desc = (PluginDescription) this.yaml.loadAs(in, (Class) PluginDescription.class);
+ desc.setFile(file);
+ this.toLoad.put(desc.getName(), desc);
+ }
+ } catch (Exception ex) {
+ ProxyServer.getInstance().getLogger().log(Level.WARNING, "Could not load plugin from file " + file, ex);
+ }
+ }
+ }
+ }
+
+ public T callEvent(final T event) {
+ Preconditions.checkNotNull((Object) event, (Object) "event");
+ final long start = System.nanoTime();
+ this.eventBus.post(event);
+ event.postCall();
+ final long elapsed = start - System.nanoTime();
+ if (elapsed > 250000L) {
+ ProxyServer.getInstance().getLogger().log(Level.WARNING, "Event {0} took more {1}ns to process!", new Object[] { event, elapsed });
+ }
+ return event;
+ }
+
+ public void registerListener(final Plugin plugin, final Listener listener) {
+ for (final Method method : listener.getClass().getDeclaredMethods()) {
+ if (method.isAnnotationPresent((Class extends Annotation>) Subscribe.class)) {
+ this.proxy.getLogger().log(Level.WARNING,
+ "Listener " + listener + " has registered using depreceated subscribe annotation!" + " Please advice author to update to @EventHandler." + " As a server owner you may safely ignore this.", new Exception());
+ }
+ }
+ this.eventBus.register(listener);
+ }
+
+ @ConstructorProperties({ "proxy", "eventBus" })
+ public PluginManager(final ProxyServer proxy, final EventBus eventBus) {
+ this.yaml = new Yaml();
+ this.plugins = new LinkedHashMap();
+ this.commandMap = new HashMap();
+ this.toLoad = new HashMap();
+ this.proxy = proxy;
+ this.eventBus = eventBus;
+ }
+
+ static {
+ argsSplit = Pattern.compile(" ");
+ }
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/api/scheduler/ScheduledTask.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/scheduler/ScheduledTask.java
new file mode 100644
index 0000000..c33f6dd
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/scheduler/ScheduledTask.java
@@ -0,0 +1,18 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.api.scheduler;
+
+import java.util.concurrent.TimeUnit;
+import net.md_5.bungee.api.plugin.Plugin;
+
+public interface ScheduledTask {
+ int getId();
+
+ Plugin getOwner();
+
+ Runnable getTask();
+
+ long getDelay(final TimeUnit p0);
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/api/scheduler/TaskScheduler.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/scheduler/TaskScheduler.java
new file mode 100644
index 0000000..1cd4fe7
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/scheduler/TaskScheduler.java
@@ -0,0 +1,22 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.api.scheduler;
+
+import java.util.concurrent.TimeUnit;
+import net.md_5.bungee.api.plugin.Plugin;
+
+public interface TaskScheduler {
+ void cancel(final int p0);
+
+ void cancel(final ScheduledTask p0);
+
+ int cancel(final Plugin p0);
+
+ ScheduledTask runAsync(final Plugin p0, final Runnable p1);
+
+ ScheduledTask schedule(final Plugin p0, final Runnable p1, final long p2, final TimeUnit p3);
+
+ ScheduledTask schedule(final Plugin p0, final Runnable p1, final long p2, final long p3, final TimeUnit p4);
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/api/score/Objective.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/score/Objective.java
new file mode 100644
index 0000000..60a2724
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/score/Objective.java
@@ -0,0 +1,82 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.api.score;
+
+import java.beans.ConstructorProperties;
+
+public class Objective {
+ private final String name;
+ private final String value;
+
+ @ConstructorProperties({ "name", "value" })
+ public Objective(final String name, final String value) {
+ this.name = name;
+ this.value = value;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public String getValue() {
+ return this.value;
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (o == this) {
+ return true;
+ }
+ if (!(o instanceof Objective)) {
+ return false;
+ }
+ final Objective other = (Objective) o;
+ if (!other.canEqual(this)) {
+ return false;
+ }
+ final Object this$name = this.getName();
+ final Object other$name = other.getName();
+ Label_0065: {
+ if (this$name == null) {
+ if (other$name == null) {
+ break Label_0065;
+ }
+ } else if (this$name.equals(other$name)) {
+ break Label_0065;
+ }
+ return false;
+ }
+ final Object this$value = this.getValue();
+ final Object other$value = other.getValue();
+ if (this$value == null) {
+ if (other$value == null) {
+ return true;
+ }
+ } else if (this$value.equals(other$value)) {
+ return true;
+ }
+ return false;
+ }
+
+ public boolean canEqual(final Object other) {
+ return other instanceof Objective;
+ }
+
+ @Override
+ public int hashCode() {
+ final int PRIME = 31;
+ int result = 1;
+ final Object $name = this.getName();
+ result = result * 31 + (($name == null) ? 0 : $name.hashCode());
+ final Object $value = this.getValue();
+ result = result * 31 + (($value == null) ? 0 : $value.hashCode());
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "Objective(name=" + this.getName() + ", value=" + this.getValue() + ")";
+ }
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/api/score/Position.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/score/Position.java
new file mode 100644
index 0000000..8cc5d54
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/score/Position.java
@@ -0,0 +1,9 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.api.score;
+
+public enum Position {
+ LIST, SIDEBAR, BELOW;
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/api/score/Score.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/score/Score.java
new file mode 100644
index 0000000..360626c
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/score/Score.java
@@ -0,0 +1,89 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.api.score;
+
+import java.beans.ConstructorProperties;
+
+public class Score {
+ private final String itemName;
+ private final String scoreName;
+ private final int value;
+
+ @ConstructorProperties({ "itemName", "scoreName", "value" })
+ public Score(final String itemName, final String scoreName, final int value) {
+ this.itemName = itemName;
+ this.scoreName = scoreName;
+ this.value = value;
+ }
+
+ public String getItemName() {
+ return this.itemName;
+ }
+
+ public String getScoreName() {
+ return this.scoreName;
+ }
+
+ public int getValue() {
+ return this.value;
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (o == this) {
+ return true;
+ }
+ if (!(o instanceof Score)) {
+ return false;
+ }
+ final Score other = (Score) o;
+ if (!other.canEqual(this)) {
+ return false;
+ }
+ final Object this$itemName = this.getItemName();
+ final Object other$itemName = other.getItemName();
+ Label_0065: {
+ if (this$itemName == null) {
+ if (other$itemName == null) {
+ break Label_0065;
+ }
+ } else if (this$itemName.equals(other$itemName)) {
+ break Label_0065;
+ }
+ return false;
+ }
+ final Object this$scoreName = this.getScoreName();
+ final Object other$scoreName = other.getScoreName();
+ if (this$scoreName == null) {
+ if (other$scoreName == null) {
+ return this.getValue() == other.getValue();
+ }
+ } else if (this$scoreName.equals(other$scoreName)) {
+ return this.getValue() == other.getValue();
+ }
+ return false;
+ }
+
+ public boolean canEqual(final Object other) {
+ return other instanceof Score;
+ }
+
+ @Override
+ public int hashCode() {
+ final int PRIME = 31;
+ int result = 1;
+ final Object $itemName = this.getItemName();
+ result = result * 31 + (($itemName == null) ? 0 : $itemName.hashCode());
+ final Object $scoreName = this.getScoreName();
+ result = result * 31 + (($scoreName == null) ? 0 : $scoreName.hashCode());
+ result = result * 31 + this.getValue();
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "Score(itemName=" + this.getItemName() + ", scoreName=" + this.getScoreName() + ", value=" + this.getValue() + ")";
+ }
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/api/score/Scoreboard.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/score/Scoreboard.java
new file mode 100644
index 0000000..ff076d8
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/score/Scoreboard.java
@@ -0,0 +1,192 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.api.score;
+
+import java.util.HashMap;
+import com.google.common.base.Preconditions;
+import java.util.Collections;
+import java.util.Collection;
+import java.util.Map;
+
+public class Scoreboard {
+ private String name;
+ private Position position;
+ private final Map objectives;
+ private final Map scores;
+ private final Map teams;
+
+ public Collection getObjectives() {
+ return Collections.unmodifiableCollection((Collection extends Objective>) this.objectives.values());
+ }
+
+ public Collection getScores() {
+ return Collections.unmodifiableCollection((Collection extends Score>) this.scores.values());
+ }
+
+ public Collection getTeams() {
+ return Collections.unmodifiableCollection((Collection extends Team>) this.teams.values());
+ }
+
+ public void addObjective(final Objective objective) {
+ Preconditions.checkNotNull((Object) objective, (Object) "objective");
+ Preconditions.checkArgument(!this.objectives.containsKey(objective.getName()), "Objective %s already exists in this scoreboard", new Object[] { objective.getName() });
+ this.objectives.put(objective.getName(), objective);
+ }
+
+ public void addScore(final Score score) {
+ Preconditions.checkNotNull((Object) score, (Object) "score");
+ this.scores.put(score.getItemName(), score);
+ }
+
+ public void addTeam(final Team team) {
+ Preconditions.checkNotNull((Object) team, (Object) "team");
+ Preconditions.checkArgument(!this.teams.containsKey(team.getName()), "Team %s already exists in this scoreboard", new Object[] { team.getName() });
+ this.teams.put(team.getName(), team);
+ }
+
+ public Team getTeam(final String name) {
+ return this.teams.get(name);
+ }
+
+ public void removeObjective(final String objectiveName) {
+ this.objectives.remove(objectiveName);
+ }
+
+ public void removeScore(final String scoreName) {
+ this.scores.remove(scoreName);
+ }
+
+ public void removeTeam(final String teamName) {
+ this.teams.remove(teamName);
+ }
+
+ public void clear() {
+ this.name = null;
+ this.position = null;
+ this.objectives.clear();
+ this.scores.clear();
+ this.teams.clear();
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public Position getPosition() {
+ return this.position;
+ }
+
+ public void setName(final String name) {
+ this.name = name;
+ }
+
+ public void setPosition(final Position position) {
+ this.position = position;
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (o == this) {
+ return true;
+ }
+ if (!(o instanceof Scoreboard)) {
+ return false;
+ }
+ final Scoreboard other = (Scoreboard) o;
+ if (!other.canEqual(this)) {
+ return false;
+ }
+ final Object this$name = this.getName();
+ final Object other$name = other.getName();
+ Label_0065: {
+ if (this$name == null) {
+ if (other$name == null) {
+ break Label_0065;
+ }
+ } else if (this$name.equals(other$name)) {
+ break Label_0065;
+ }
+ return false;
+ }
+ final Object this$position = this.getPosition();
+ final Object other$position = other.getPosition();
+ Label_0102: {
+ if (this$position == null) {
+ if (other$position == null) {
+ break Label_0102;
+ }
+ } else if (this$position.equals(other$position)) {
+ break Label_0102;
+ }
+ return false;
+ }
+ final Object this$objectives = this.getObjectives();
+ final Object other$objectives = other.getObjectives();
+ Label_0139: {
+ if (this$objectives == null) {
+ if (other$objectives == null) {
+ break Label_0139;
+ }
+ } else if (this$objectives.equals(other$objectives)) {
+ break Label_0139;
+ }
+ return false;
+ }
+ final Object this$scores = this.getScores();
+ final Object other$scores = other.getScores();
+ Label_0176: {
+ if (this$scores == null) {
+ if (other$scores == null) {
+ break Label_0176;
+ }
+ } else if (this$scores.equals(other$scores)) {
+ break Label_0176;
+ }
+ return false;
+ }
+ final Object this$teams = this.getTeams();
+ final Object other$teams = other.getTeams();
+ if (this$teams == null) {
+ if (other$teams == null) {
+ return true;
+ }
+ } else if (this$teams.equals(other$teams)) {
+ return true;
+ }
+ return false;
+ }
+
+ public boolean canEqual(final Object other) {
+ return other instanceof Scoreboard;
+ }
+
+ @Override
+ public int hashCode() {
+ final int PRIME = 31;
+ int result = 1;
+ final Object $name = this.getName();
+ result = result * 31 + (($name == null) ? 0 : $name.hashCode());
+ final Object $position = this.getPosition();
+ result = result * 31 + (($position == null) ? 0 : $position.hashCode());
+ final Object $objectives = this.getObjectives();
+ result = result * 31 + (($objectives == null) ? 0 : $objectives.hashCode());
+ final Object $scores = this.getScores();
+ result = result * 31 + (($scores == null) ? 0 : $scores.hashCode());
+ final Object $teams = this.getTeams();
+ result = result * 31 + (($teams == null) ? 0 : $teams.hashCode());
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "Scoreboard(name=" + this.getName() + ", position=" + this.getPosition() + ", objectives=" + this.getObjectives() + ", scores=" + this.getScores() + ", teams=" + this.getTeams() + ")";
+ }
+
+ public Scoreboard() {
+ this.objectives = new HashMap();
+ this.scores = new HashMap();
+ this.teams = new HashMap();
+ }
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/api/score/Team.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/score/Team.java
new file mode 100644
index 0000000..091469b
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/score/Team.java
@@ -0,0 +1,183 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.api.score;
+
+import java.beans.ConstructorProperties;
+import java.util.HashSet;
+import java.util.Collections;
+import java.util.Collection;
+import java.util.Set;
+
+public class Team {
+ private final String name;
+ private String displayName;
+ private String prefix;
+ private String suffix;
+ private boolean friendlyFire;
+ private Set players;
+
+ public Collection getPlayers() {
+ return (Collection) Collections.unmodifiableSet((Set>) this.players);
+ }
+
+ public void addPlayer(final String name) {
+ this.players.add(name);
+ }
+
+ public void removePlayer(final String name) {
+ this.players.remove(name);
+ }
+
+ @ConstructorProperties({ "name" })
+ public Team(final String name) {
+ this.players = new HashSet();
+ if (name == null) {
+ throw new NullPointerException("name");
+ }
+ this.name = name;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public String getDisplayName() {
+ return this.displayName;
+ }
+
+ public String getPrefix() {
+ return this.prefix;
+ }
+
+ public String getSuffix() {
+ return this.suffix;
+ }
+
+ public boolean isFriendlyFire() {
+ return this.friendlyFire;
+ }
+
+ public void setDisplayName(final String displayName) {
+ this.displayName = displayName;
+ }
+
+ public void setPrefix(final String prefix) {
+ this.prefix = prefix;
+ }
+
+ public void setSuffix(final String suffix) {
+ this.suffix = suffix;
+ }
+
+ public void setFriendlyFire(final boolean friendlyFire) {
+ this.friendlyFire = friendlyFire;
+ }
+
+ public void setPlayers(final Set players) {
+ this.players = players;
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (o == this) {
+ return true;
+ }
+ if (!(o instanceof Team)) {
+ return false;
+ }
+ final Team other = (Team) o;
+ if (!other.canEqual(this)) {
+ return false;
+ }
+ final Object this$name = this.getName();
+ final Object other$name = other.getName();
+ Label_0065: {
+ if (this$name == null) {
+ if (other$name == null) {
+ break Label_0065;
+ }
+ } else if (this$name.equals(other$name)) {
+ break Label_0065;
+ }
+ return false;
+ }
+ final Object this$displayName = this.getDisplayName();
+ final Object other$displayName = other.getDisplayName();
+ Label_0102: {
+ if (this$displayName == null) {
+ if (other$displayName == null) {
+ break Label_0102;
+ }
+ } else if (this$displayName.equals(other$displayName)) {
+ break Label_0102;
+ }
+ return false;
+ }
+ final Object this$prefix = this.getPrefix();
+ final Object other$prefix = other.getPrefix();
+ Label_0139: {
+ if (this$prefix == null) {
+ if (other$prefix == null) {
+ break Label_0139;
+ }
+ } else if (this$prefix.equals(other$prefix)) {
+ break Label_0139;
+ }
+ return false;
+ }
+ final Object this$suffix = this.getSuffix();
+ final Object other$suffix = other.getSuffix();
+ Label_0176: {
+ if (this$suffix == null) {
+ if (other$suffix == null) {
+ break Label_0176;
+ }
+ } else if (this$suffix.equals(other$suffix)) {
+ break Label_0176;
+ }
+ return false;
+ }
+ if (this.isFriendlyFire() != other.isFriendlyFire()) {
+ return false;
+ }
+ final Object this$players = this.getPlayers();
+ final Object other$players = other.getPlayers();
+ if (this$players == null) {
+ if (other$players == null) {
+ return true;
+ }
+ } else if (this$players.equals(other$players)) {
+ return true;
+ }
+ return false;
+ }
+
+ public boolean canEqual(final Object other) {
+ return other instanceof Team;
+ }
+
+ @Override
+ public int hashCode() {
+ final int PRIME = 31;
+ int result = 1;
+ final Object $name = this.getName();
+ result = result * 31 + (($name == null) ? 0 : $name.hashCode());
+ final Object $displayName = this.getDisplayName();
+ result = result * 31 + (($displayName == null) ? 0 : $displayName.hashCode());
+ final Object $prefix = this.getPrefix();
+ result = result * 31 + (($prefix == null) ? 0 : $prefix.hashCode());
+ final Object $suffix = this.getSuffix();
+ result = result * 31 + (($suffix == null) ? 0 : $suffix.hashCode());
+ result = result * 31 + (this.isFriendlyFire() ? 1231 : 1237);
+ final Object $players = this.getPlayers();
+ result = result * 31 + (($players == null) ? 0 : $players.hashCode());
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "Team(name=" + this.getName() + ", displayName=" + this.getDisplayName() + ", prefix=" + this.getPrefix() + ", suffix=" + this.getSuffix() + ", friendlyFire=" + this.isFriendlyFire() + ", players=" + this.getPlayers() + ")";
+ }
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/api/tab/CustomTabList.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/tab/CustomTabList.java
new file mode 100644
index 0000000..b0e0006
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/tab/CustomTabList.java
@@ -0,0 +1,21 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.api.tab;
+
+public interface CustomTabList extends TabListHandler {
+ void clear();
+
+ int getColumns();
+
+ int getRows();
+
+ int getSize();
+
+ String setSlot(final int p0, final int p1, final String p2);
+
+ String setSlot(final int p0, final int p1, final String p2, final boolean p3);
+
+ void update();
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/api/tab/TabListAdapter.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/tab/TabListAdapter.java
new file mode 100644
index 0000000..3f8661b
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/tab/TabListAdapter.java
@@ -0,0 +1,36 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.api.tab;
+
+import net.md_5.bungee.api.connection.ProxiedPlayer;
+
+public abstract class TabListAdapter implements TabListHandler {
+ private ProxiedPlayer player;
+
+ @Override
+ public void init(final ProxiedPlayer player) {
+ this.player = player;
+ }
+
+ @Override
+ public void onConnect() {
+ }
+
+ @Override
+ public void onDisconnect() {
+ }
+
+ @Override
+ public void onServerChange() {
+ }
+
+ @Override
+ public void onPingChange(final int ping) {
+ }
+
+ public ProxiedPlayer getPlayer() {
+ return this.player;
+ }
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/api/tab/TabListHandler.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/tab/TabListHandler.java
new file mode 100644
index 0000000..2e7ca50
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/api/tab/TabListHandler.java
@@ -0,0 +1,21 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.api.tab;
+
+import net.md_5.bungee.api.connection.ProxiedPlayer;
+
+public interface TabListHandler {
+ void init(final ProxiedPlayer p0);
+
+ void onConnect();
+
+ void onServerChange();
+
+ void onPingChange(final int p0);
+
+ void onDisconnect();
+
+ boolean onListUpdate(final String p0, final boolean p1, final int p2);
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/command/CommandAlert.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/command/CommandAlert.java
new file mode 100644
index 0000000..d77d5ab
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/command/CommandAlert.java
@@ -0,0 +1,37 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.command;
+
+import net.md_5.bungee.api.ProxyServer;
+import net.md_5.bungee.api.ChatColor;
+import net.md_5.bungee.api.CommandSender;
+import net.md_5.bungee.api.plugin.Command;
+
+public class CommandAlert extends Command {
+ public CommandAlert() {
+ super("alert", "bungeecord.command.alert", new String[0]);
+ }
+
+ @Override
+ public void execute(final CommandSender sender, final String[] args) {
+ if (args.length == 0) {
+ sender.sendMessage(ChatColor.RED + "You must supply a message.");
+ } else {
+ final StringBuilder builder = new StringBuilder();
+ if (args[0].startsWith("&h")) {
+ args[0] = args[0].substring(2, args[0].length());
+ } else {
+ builder.append(ProxyServer.getInstance().getTranslation("alert"));
+ }
+ for (final String s : args) {
+ builder.append(ChatColor.translateAlternateColorCodes('&', s));
+ builder.append(" ");
+ }
+ final String message = builder.substring(0, builder.length() - 1);
+ ProxyServer.getInstance().broadcast(message);
+ ProxyServer.getInstance().getConsole().sendMessage(message);
+ }
+ }
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/command/CommandBungee.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/command/CommandBungee.java
new file mode 100644
index 0000000..5cc0e2b
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/command/CommandBungee.java
@@ -0,0 +1,21 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.command;
+
+import net.md_5.bungee.api.ProxyServer;
+import net.md_5.bungee.api.ChatColor;
+import net.md_5.bungee.api.CommandSender;
+import net.md_5.bungee.api.plugin.Command;
+
+public class CommandBungee extends Command {
+ public CommandBungee() {
+ super("bungee");
+ }
+
+ @Override
+ public void execute(final CommandSender sender, final String[] args) {
+ sender.sendMessage(ChatColor.BLUE + "This server is running BungeeCord version " + ProxyServer.getInstance().getVersion() + " by md_5");
+ }
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/command/CommandEnd.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/command/CommandEnd.java
new file mode 100644
index 0000000..2e52624
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/command/CommandEnd.java
@@ -0,0 +1,20 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.command;
+
+import net.md_5.bungee.BungeeCord;
+import net.md_5.bungee.api.CommandSender;
+import net.md_5.bungee.api.plugin.Command;
+
+public class CommandEnd extends Command {
+ public CommandEnd() {
+ super("end", "bungeecord.command.end", new String[0]);
+ }
+
+ @Override
+ public void execute(final CommandSender sender, final String[] args) {
+ BungeeCord.getInstance().stop();
+ }
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/command/CommandFind.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/command/CommandFind.java
new file mode 100644
index 0000000..d146f5e
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/command/CommandFind.java
@@ -0,0 +1,31 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.command;
+
+import net.md_5.bungee.api.connection.ProxiedPlayer;
+import net.md_5.bungee.api.ProxyServer;
+import net.md_5.bungee.api.ChatColor;
+import net.md_5.bungee.api.CommandSender;
+import net.md_5.bungee.api.plugin.Command;
+
+public class CommandFind extends Command {
+ public CommandFind() {
+ super("find", "bungeecord.command.find", new String[0]);
+ }
+
+ @Override
+ public void execute(final CommandSender sender, final String[] args) {
+ if (args.length != 1) {
+ sender.sendMessage(ChatColor.RED + "Please follow this command by a user name");
+ } else {
+ final ProxiedPlayer player = ProxyServer.getInstance().getPlayer(args[0]);
+ if (player == null || player.getServer() == null) {
+ sender.sendMessage(ChatColor.RED + "That user is not online");
+ } else {
+ sender.sendMessage(ChatColor.BLUE + args[0] + " is online at " + player.getServer().getInfo().getName());
+ }
+ }
+ }
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/command/CommandIP.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/command/CommandIP.java
new file mode 100644
index 0000000..376fbfb
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/command/CommandIP.java
@@ -0,0 +1,31 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.command;
+
+import net.md_5.bungee.api.connection.ProxiedPlayer;
+import net.md_5.bungee.api.ProxyServer;
+import net.md_5.bungee.api.ChatColor;
+import net.md_5.bungee.api.CommandSender;
+import net.md_5.bungee.api.plugin.Command;
+
+public class CommandIP extends Command {
+ public CommandIP() {
+ super("ip", "bungeecord.command.ip", new String[0]);
+ }
+
+ @Override
+ public void execute(final CommandSender sender, final String[] args) {
+ if (args.length < 1) {
+ sender.sendMessage(ChatColor.RED + "Please follow this command by a user name");
+ return;
+ }
+ final ProxiedPlayer user = ProxyServer.getInstance().getPlayer(args[0]);
+ if (user == null) {
+ sender.sendMessage(ChatColor.RED + "That user is not online");
+ } else {
+ sender.sendMessage(ChatColor.BLUE + "IP of " + args[0] + " is " + user.getAddress());
+ }
+ }
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/command/CommandList.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/command/CommandList.java
new file mode 100644
index 0000000..10d50e8
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/command/CommandList.java
@@ -0,0 +1,53 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.command;
+
+import java.util.List;
+import java.util.Iterator;
+import java.util.Collection;
+import net.md_5.bungee.Util;
+import java.util.Comparator;
+import java.util.Collections;
+import net.md_5.bungee.api.connection.ProxiedPlayer;
+import java.util.ArrayList;
+import net.md_5.bungee.api.ChatColor;
+import net.md_5.bungee.api.config.ServerInfo;
+import net.md_5.bungee.api.ProxyServer;
+import net.md_5.bungee.api.CommandSender;
+import net.md_5.bungee.api.plugin.Command;
+
+public class CommandList extends Command {
+ public CommandList() {
+ super("glist", "bungeecord.command.list", new String[0]);
+ }
+
+ @Override
+ public void execute(final CommandSender sender, final String[] args) {
+ for (final ServerInfo server : ProxyServer.getInstance().getServers().values()) {
+ if (!server.canAccess(sender)) {
+ continue;
+ }
+ final Collection serverPlayers = server.getPlayers();
+ final 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);
+ final List players = new ArrayList();
+ for (final ProxiedPlayer player : serverPlayers) {
+ 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("total_players") + ProxyServer.getInstance().getOnlineCount());
+ }
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/command/CommandPerms.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/command/CommandPerms.java
new file mode 100644
index 0000000..1db3eea
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/command/CommandPerms.java
@@ -0,0 +1,35 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.command;
+
+import java.util.Iterator;
+import java.util.Set;
+import net.md_5.bungee.api.ChatColor;
+import java.util.Collection;
+import net.md_5.bungee.api.ProxyServer;
+import java.util.HashSet;
+import net.md_5.bungee.api.CommandSender;
+import net.md_5.bungee.api.plugin.Command;
+
+public class CommandPerms extends Command {
+ public CommandPerms() {
+ super("perms");
+ }
+
+ @Override
+ public void execute(final CommandSender sender, final String[] args) {
+ final StringBuilder groups = new StringBuilder();
+ final Set permissions = new HashSet();
+ for (final String group : sender.getGroups()) {
+ groups.append(group);
+ groups.append(", ");
+ permissions.addAll(ProxyServer.getInstance().getConfigurationAdapter().getPermissions(group));
+ }
+ sender.sendMessage(ChatColor.GOLD + "You have the following groups: " + groups.substring(0, groups.length() - 2));
+ for (final String permission : permissions) {
+ sender.sendMessage(ChatColor.BLUE + "- " + permission);
+ }
+ }
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/command/CommandReload.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/command/CommandReload.java
new file mode 100644
index 0000000..d5d2b37
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/command/CommandReload.java
@@ -0,0 +1,24 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.command;
+
+import net.md_5.bungee.api.ChatColor;
+import net.md_5.bungee.BungeeCord;
+import net.md_5.bungee.api.CommandSender;
+import net.md_5.bungee.api.plugin.Command;
+
+public class CommandReload extends Command {
+ public CommandReload() {
+ super("greload", "bungeecord.command.reload", new String[0]);
+ }
+
+ @Override
+ public void execute(final CommandSender sender, final String[] args) {
+ BungeeCord.getInstance().config.load();
+ BungeeCord.getInstance().stopListeners();
+ BungeeCord.getInstance().startListeners();
+ sender.sendMessage(ChatColor.BOLD.toString() + ChatColor.RED.toString() + "BungeeCord has been reloaded." + " This is NOT advisable and you will not be supported with any issues that arise! Please restart BungeeCord ASAP.");
+ }
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/command/CommandSend.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/command/CommandSend.java
new file mode 100644
index 0000000..21ee18b
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/command/CommandSend.java
@@ -0,0 +1,61 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.command;
+
+import java.util.Iterator;
+import net.md_5.bungee.api.config.ServerInfo;
+import net.md_5.bungee.api.connection.ProxiedPlayer;
+import net.md_5.bungee.api.ProxyServer;
+import net.md_5.bungee.api.ChatColor;
+import net.md_5.bungee.api.CommandSender;
+import net.md_5.bungee.api.plugin.Command;
+
+public class CommandSend extends Command {
+ public CommandSend() {
+ super("send", "bungeecord.command.send", new String[0]);
+ }
+
+ @Override
+ public void execute(final CommandSender sender, final String[] args) {
+ if (args.length != 2) {
+ sender.sendMessage(ChatColor.RED + "Not enough arguments, usage: /send ");
+ return;
+ }
+ final ServerInfo target = ProxyServer.getInstance().getServerInfo(args[1]);
+ if (target == null) {
+ sender.sendMessage(ProxyServer.getInstance().getTranslation("no_server"));
+ return;
+ }
+ if (args[0].equalsIgnoreCase("all")) {
+ for (final ProxiedPlayer p : ProxyServer.getInstance().getPlayers()) {
+ this.summon(p, target, sender);
+ }
+ } else if (args[0].equalsIgnoreCase("current")) {
+ if (!(sender instanceof ProxiedPlayer)) {
+ sender.sendMessage(ChatColor.RED + "Only in game players can use this command");
+ return;
+ }
+ final ProxiedPlayer player = (ProxiedPlayer) sender;
+ for (final ProxiedPlayer p2 : player.getServer().getInfo().getPlayers()) {
+ this.summon(p2, target, sender);
+ }
+ } else {
+ final ProxiedPlayer player = ProxyServer.getInstance().getPlayer(args[0]);
+ if (player == null) {
+ sender.sendMessage(ChatColor.RED + "That player is not online");
+ return;
+ }
+ this.summon(player, target, sender);
+ }
+ sender.sendMessage(ChatColor.GREEN + "Successfully summoned player(s)");
+ }
+
+ private void summon(final ProxiedPlayer player, final ServerInfo target, final CommandSender sender) {
+ if (player.getServer() != null && !player.getServer().getInfo().equals(target)) {
+ player.connect(target);
+ player.sendMessage(ChatColor.GOLD + "Summoned to " + target.getName() + " by " + sender.getName());
+ }
+ }
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/command/CommandServer.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/command/CommandServer.java
new file mode 100644
index 0000000..85f69fe
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/command/CommandServer.java
@@ -0,0 +1,51 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.command;
+
+import java.util.Iterator;
+import java.util.Map;
+import net.md_5.bungee.api.config.ServerInfo;
+import net.md_5.bungee.api.ProxyServer;
+import net.md_5.bungee.api.connection.ProxiedPlayer;
+import net.md_5.bungee.api.CommandSender;
+import net.md_5.bungee.api.plugin.Command;
+
+public class CommandServer extends Command {
+ public CommandServer() {
+ super("server", "bungeecord.command.server", new String[0]);
+ }
+
+ @Override
+ public void execute(final CommandSender sender, final String[] args) {
+ if (!(sender instanceof ProxiedPlayer)) {
+ return;
+ }
+ final ProxiedPlayer player = (ProxiedPlayer) sender;
+ final Map servers = ProxyServer.getInstance().getServers();
+ if (args.length == 0) {
+ player.sendMessage(ProxyServer.getInstance().getTranslation("current_server") + player.getServer().getInfo().getName());
+ final StringBuilder serverList = new StringBuilder();
+ for (final ServerInfo server : servers.values()) {
+ if (server.canAccess(player)) {
+ serverList.append(server.getName());
+ serverList.append(", ");
+ }
+ }
+ if (serverList.length() != 0) {
+ serverList.setLength(serverList.length() - 2);
+ }
+ player.sendMessage(ProxyServer.getInstance().getTranslation("server_list") + serverList.toString());
+ } else {
+ final ServerInfo server2 = servers.get(args[0]);
+ if (server2 == null) {
+ player.sendMessage(ProxyServer.getInstance().getTranslation("no_server"));
+ } else if (!server2.canAccess(player)) {
+ player.sendMessage(ProxyServer.getInstance().getTranslation("no_server_permission"));
+ } else {
+ player.connect(server2);
+ }
+ }
+ }
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/command/ConsoleCommandSender.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/command/ConsoleCommandSender.java
new file mode 100644
index 0000000..c9f4cd4
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/command/ConsoleCommandSender.java
@@ -0,0 +1,68 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.command;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Collection;
+import net.md_5.bungee.api.ProxyServer;
+import net.md_5.bungee.api.CommandSender;
+
+public class ConsoleCommandSender implements CommandSender {
+ private static final ConsoleCommandSender instance;
+
+ private ConsoleCommandSender() {
+ }
+
+ @Override
+ public void sendMessage(final String message) {
+ ProxyServer.getInstance().getLogger().info(message);
+ }
+
+ @Override
+ public void sendMessages(final String... messages) {
+ for (final String message : messages) {
+ this.sendMessage(message);
+ }
+ }
+
+ @Override
+ public String getName() {
+ return "CONSOLE";
+ }
+
+ @Override
+ public Collection getGroups() {
+ return (Collection) new HashSet();
+ }
+
+ @Override
+ public void addGroups(final String... groups) {
+ throw new UnsupportedOperationException("Console may not have groups");
+ }
+
+ @Override
+ public void removeGroups(final String... groups) {
+ throw new UnsupportedOperationException("Console may not have groups");
+ }
+
+ @Override
+ public boolean hasPermission(final String permission) {
+ return true;
+ }
+
+ @Override
+ public void setPermission(final String permission, final boolean value) {
+ throw new UnsupportedOperationException("Console has all permissions");
+ }
+
+ public static ConsoleCommandSender getInstance() {
+ return ConsoleCommandSender.instance;
+ }
+
+ static {
+ instance = new ConsoleCommandSender();
+ }
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/config/Configuration.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/config/Configuration.java
new file mode 100644
index 0000000..dc17dcf
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/config/Configuration.java
@@ -0,0 +1,91 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.config;
+
+import net.md_5.bungee.api.config.AuthServiceInfo;
+import net.md_5.bungee.api.config.ConfigurationAdapter;
+import java.util.Map;
+import net.md_5.bungee.util.CaseInsensitiveMap;
+import com.google.common.base.Preconditions;
+import net.md_5.bungee.api.ProxyServer;
+import java.util.UUID;
+import net.md_5.bungee.api.config.ServerInfo;
+import gnu.trove.map.TMap;
+import net.md_5.bungee.api.config.ListenerInfo;
+import java.util.Collection;
+
+public class Configuration {
+ private int timeout;
+ private String uuid;
+ private Collection listeners;
+ private TMap servers;
+ private AuthServiceInfo authInfo;
+ private boolean onlineMode;
+ private int playerLimit;
+
+ public Configuration() {
+ this.timeout = 30000;
+ this.uuid = UUID.randomUUID().toString();
+ this.onlineMode = true;
+ this.playerLimit = -1;
+ }
+
+ public void load() {
+ final ConfigurationAdapter adapter = ProxyServer.getInstance().getConfigurationAdapter();
+ adapter.load();
+ this.listeners = adapter.getListeners();
+ this.timeout = adapter.getInt("timeout", this.timeout);
+ this.uuid = adapter.getString("stats", this.uuid);
+ this.authInfo = adapter.getAuthSettings();
+ this.onlineMode = false;
+ this.playerLimit = adapter.getInt("player_limit", this.playerLimit);
+ Preconditions.checkArgument(this.listeners != null && !this.listeners.isEmpty(), (Object) "No listeners defined.");
+ final Map newServers = adapter.getServers();
+ Preconditions.checkArgument(newServers != null && !newServers.isEmpty(), (Object) "No servers defined");
+ if (this.servers == null) {
+ this.servers = (TMap) new CaseInsensitiveMap(newServers);
+ } else {
+ for (final ServerInfo oldServer : this.servers.values()) {
+ Preconditions.checkArgument(newServers.containsValue(oldServer), "Server %s removed on reload!", new Object[] { oldServer.getName() });
+ }
+ for (final Map.Entry newServer : newServers.entrySet()) {
+ if (!this.servers.containsValue(newServer.getValue())) {
+ this.servers.put(newServer.getKey(), newServer.getValue());
+ }
+ }
+ }
+ for (final ListenerInfo listener : this.listeners) {
+ Preconditions.checkArgument(this.servers.containsKey((Object) listener.getDefaultServer()), "Default server %s is not defined", new Object[] { listener.getDefaultServer() });
+ }
+ }
+
+ public int getTimeout() {
+ return this.timeout;
+ }
+
+ public String getUuid() {
+ return this.uuid;
+ }
+
+ public Collection getListeners() {
+ return this.listeners;
+ }
+
+ public TMap getServers() {
+ return this.servers;
+ }
+
+ public boolean isOnlineMode() {
+ return this.onlineMode;
+ }
+
+ public int getPlayerLimit() {
+ return this.playerLimit;
+ }
+
+ public AuthServiceInfo getAuthInfo() {
+ return authInfo;
+ }
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/config/YamlConfig.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/config/YamlConfig.java
new file mode 100644
index 0000000..eabe946
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/config/YamlConfig.java
@@ -0,0 +1,209 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.config;
+
+import net.md_5.bungee.tab.ServerUnique;
+import net.md_5.bungee.tab.GlobalPing;
+import net.md_5.bungee.tab.Global;
+import net.md_5.bungee.api.tab.TabListHandler;
+import net.md_5.bungee.api.config.TexturePackInfo;
+import net.md_5.bungee.api.ChatColor;
+import java.util.HashSet;
+import net.md_5.bungee.api.config.ListenerInfo;
+import java.util.Collection;
+import java.net.InetSocketAddress;
+import java.util.Iterator;
+import net.md_5.bungee.Util;
+import net.md_5.bungee.api.config.ServerInfo;
+import java.util.logging.Level;
+import net.md_5.bungee.api.ProxyServer;
+import java.io.Writer;
+import java.io.FileWriter;
+import java.util.LinkedHashMap;
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.io.IOException;
+import net.md_5.bungee.util.CaseInsensitiveMap;
+import java.io.FileInputStream;
+import org.yaml.snakeyaml.DumperOptions;
+import java.io.File;
+import java.util.Map;
+import org.yaml.snakeyaml.Yaml;
+
+import net.md_5.bungee.api.config.AuthServiceInfo;
+import net.md_5.bungee.api.config.ConfigurationAdapter;
+
+public class YamlConfig implements ConfigurationAdapter {
+ private Yaml yaml;
+ private Map config;
+ private final File file;
+
+ public YamlConfig() {
+ this.file = new File("config.yml");
+ }
+
+ @Override
+ public void load() {
+ try {
+ this.file.createNewFile();
+ final DumperOptions options = new DumperOptions();
+ options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
+ this.yaml = new Yaml(options);
+ try (final InputStream is = new FileInputStream(this.file)) {
+ this.config = (Map) this.yaml.load(is);
+ }
+ if (this.config == null) {
+ this.config = (Map) new CaseInsensitiveMap();
+ } else {
+ this.config = (Map) new CaseInsensitiveMap(this.config);
+ }
+ } catch (IOException ex) {
+ throw new RuntimeException("Could not load configuration!", ex);
+ }
+ final Map permissions = this.get("permissions", new HashMap());
+ if (permissions.isEmpty()) {
+ permissions.put("default", Arrays.asList("bungeecord.command.server", "bungeecord.command.list"));
+ permissions.put("admin", Arrays.asList("bungeecord.command.alert", "bungeecord.command.end", "bungeecord.command.ip", "bungeecord.command.reload"));
+ }
+ final Map groups = this.get("groups", new HashMap());
+ if (groups.isEmpty()) {
+ groups.put("lax1dude", Collections.singletonList("admin"));
+ }
+ final Map auth = this.get("authservice", new HashMap());
+ if(auth.isEmpty()) {
+ auth.put("enabled", false);
+ auth.put("limbo", "lobby");
+ auth.put("authfile", "passwords.yml");
+ auth.put("timeout", 30);
+ }
+ }
+
+ private T get(final String path, final T def) {
+ return this.get(path, def, this.config);
+ }
+
+ private T get(final String path, final T def, final Map submap) {
+ final int index = path.indexOf(46);
+ if (index == -1) {
+ Object val = submap.get(path);
+ if (val == null && def != null) {
+ val = def;
+ submap.put(path, def);
+ this.save();
+ }
+ return (T) val;
+ }
+ final String first = path.substring(0, index);
+ final String second = path.substring(index + 1, path.length());
+ Map sub = (Map) submap.get(first);
+ if (sub == null) {
+ sub = new LinkedHashMap();
+ submap.put(first, sub);
+ }
+ return (T) this.get(second, (Object) def, sub);
+ }
+
+ private void save() {
+ try (final FileWriter wr = new FileWriter(this.file)) {
+ this.yaml.dump((Object) this.config, (Writer) wr);
+ } catch (IOException ex) {
+ ProxyServer.getInstance().getLogger().log(Level.WARNING, "Could not save config", ex);
+ }
+ }
+
+ @Override
+ public int getInt(final String path, final int def) {
+ return this.get(path, def);
+ }
+
+ @Override
+ public String getString(final String path, final String def) {
+ return this.get(path, def);
+ }
+
+ @Override
+ public boolean getBoolean(final String path, final boolean def) {
+ return this.get(path, def);
+ }
+
+ @Override
+ public Map getServers() {
+ final Map base = this.get("servers", (Map) Collections.singletonMap("lobby", new HashMap()));
+ final Map ret = new HashMap();
+ for (final Map.Entry entry : base.entrySet()) {
+ final Map val = entry.getValue();
+ final String name = entry.getKey();
+ final String addr = this.get("address", "localhost:25501", val);
+ final boolean restricted = this.get("restricted", false, val);
+ final InetSocketAddress address = Util.getAddr(addr);
+ final ServerInfo info = ProxyServer.getInstance().constructServerInfo(name, address, restricted);
+ ret.put(name, info);
+ }
+ return ret;
+ }
+
+ @Override
+ public Collection getListeners() {
+ final Collection base = this.get("listeners", (Collection) Arrays.asList(new HashMap()));
+ final Map forcedDef = new HashMap();
+ //forcedDef.put("pvp.md-5.net", "pvp");
+ final Collection ret = new HashSet();
+ for (final Map val : base) {
+ String motd = this.get("motd", "&6&lbungeecord eaglercraft server |>", val);
+ motd = ChatColor.translateAlternateColorCodes('&', motd);
+ final int maxPlayers = this.get("max_players", 60, val);
+ final String defaultServer = this.get("default_server", "lobby", val);
+ final String fallbackServer = this.get("fallback_server", defaultServer, val);
+ final boolean forceDefault = this.get("force_default_server", true, val);
+ final boolean websocket = this.get("websocket", true, val);
+ final String host = this.get("host", "0.0.0.0:25565", val);
+ final int tabListSize = this.get("tab_size", 60, val);
+ final InetSocketAddress address = Util.getAddr(host);
+ final Map forced = (Map) new CaseInsensitiveMap(this.get("forced_hosts", forcedDef, val));
+ final String textureURL = this.get("texture_url", (String) null, val);
+ final int textureSize = this.get("texture_size", 16, val);
+ final TexturePackInfo texture = (textureURL == null) ? null : new TexturePackInfo(textureURL, textureSize);
+ final String tabListName = this.get("tab_list", "GLOBAL_PING", val);
+ DefaultTabList value = DefaultTabList.valueOf(tabListName.toUpperCase());
+ if (value == null) {
+ value = DefaultTabList.GLOBAL_PING;
+ }
+ final ListenerInfo info = new ListenerInfo(address, motd, maxPlayers, tabListSize, defaultServer, fallbackServer, forceDefault, websocket, forced, texture, value.clazz);
+ ret.add(info);
+ }
+ return ret;
+ }
+
+ @Override
+ public Collection getGroups(final String player) {
+ final Collection groups = this.get("groups." + player, (Collection) null);
+ final Collection ret = (groups == null) ? new HashSet() : new HashSet(groups);
+ ret.add("default");
+ return ret;
+ }
+
+ @Override
+ public Collection getPermissions(final String group) {
+ return this.get("permissions." + group, (Collection) Collections.EMPTY_LIST);
+ }
+
+ private enum DefaultTabList {
+ GLOBAL((Class extends TabListHandler>) Global.class), GLOBAL_PING((Class extends TabListHandler>) GlobalPing.class), SERVER((Class extends TabListHandler>) ServerUnique.class);
+
+ private final Class extends TabListHandler> clazz;
+
+ private DefaultTabList(final Class extends TabListHandler> clazz) {
+ this.clazz = clazz;
+ }
+ }
+
+ @Override
+ public AuthServiceInfo getAuthSettings() {
+ final Map auth = this.get("authservice", new HashMap());
+ return new AuthServiceInfo(this.get("enabled", true, auth), this.get("limbo", "lobby", auth), new File(this.get("authfile", "passwords.yml", auth)), this.get("timeout", 30, auth));
+ }
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/connection/CancelSendSignal.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/connection/CancelSendSignal.java
new file mode 100644
index 0000000..a0bdda3
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/connection/CancelSendSignal.java
@@ -0,0 +1,17 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.connection;
+
+public class CancelSendSignal extends Error {
+ @Override
+ public Throwable initCause(final Throwable cause) {
+ return this;
+ }
+
+ @Override
+ public Throwable fillInStackTrace() {
+ return this;
+ }
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/connection/DownstreamBridge.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/connection/DownstreamBridge.java
new file mode 100644
index 0000000..39012fb
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/connection/DownstreamBridge.java
@@ -0,0 +1,285 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.connection;
+
+import java.beans.ConstructorProperties;
+import net.md_5.bungee.api.event.ServerKickEvent;
+import java.util.Objects;
+import net.md_5.bungee.protocol.packet.PacketFFKick;
+import java.util.Iterator;
+import com.google.common.io.ByteArrayDataOutput;
+import com.google.common.io.ByteArrayDataInput;
+import java.util.Collection;
+import net.md_5.bungee.api.connection.Connection;
+import net.md_5.bungee.api.event.PluginMessageEvent;
+import com.google.common.io.ByteStreams;
+import net.md_5.bungee.protocol.packet.PacketFAPluginMessage;
+import net.md_5.bungee.api.score.Team;
+import net.md_5.bungee.protocol.packet.PacketD1Team;
+import net.md_5.bungee.api.score.Position;
+import net.md_5.bungee.protocol.packet.PacketD0DisplayScoreboard;
+import net.md_5.bungee.api.score.Score;
+import net.md_5.bungee.protocol.packet.PacketCFScoreboardScore;
+import net.md_5.bungee.api.score.Scoreboard;
+import net.md_5.bungee.api.score.Objective;
+import net.md_5.bungee.protocol.packet.PacketCEScoreboardObjective;
+import net.md_5.bungee.protocol.packet.PacketC9PlayerListItem;
+import net.md_5.bungee.protocol.packet.Packet0KeepAlive;
+import net.md_5.bungee.EntityMap;
+import net.md_5.bungee.api.connection.ProxiedPlayer;
+import net.md_5.bungee.netty.ChannelWrapper;
+import net.md_5.bungee.api.config.ServerInfo;
+import net.md_5.bungee.Util;
+import net.md_5.bungee.api.ChatColor;
+import net.md_5.bungee.ServerConnection;
+import net.md_5.bungee.UserConnection;
+import net.md_5.bungee.api.ProxyServer;
+import net.md_5.bungee.netty.PacketHandler;
+
+public class DownstreamBridge extends PacketHandler {
+ private final ProxyServer bungee;
+ private final UserConnection con;
+ private final ServerConnection server;
+
+ @Override
+ public void exception(final Throwable t) throws Exception {
+ final ServerInfo def = this.bungee.getServerInfo(this.con.getPendingConnection().getListener().getFallbackServer());
+ if (this.server.getInfo() != def) {
+ this.con.connectNow(def);
+ this.con.sendMessage(ChatColor.RED + "The server you were previously on went down, you have been connected to the lobby");
+ } else {
+ this.con.disconnect(Util.exception(t));
+ }
+ }
+
+ @Override
+ public void disconnected(final ChannelWrapper channel) throws Exception {
+ this.server.getInfo().removePlayer(this.con);
+ this.bungee.getReconnectHandler().setServer(this.con);
+ if (!this.server.isObsolete()) {
+ this.con.disconnect(this.bungee.getTranslation("lost_connection"));
+ }
+ }
+
+ @Override
+ public void handle(final byte[] buf) throws Exception {
+ if (!this.server.isObsolete()) {
+ EntityMap.rewrite(buf, this.con.getServerEntityId(), this.con.getClientEntityId());
+ this.con.sendPacket(buf);
+ }
+ }
+
+ @Override
+ public void handle(final Packet0KeepAlive alive) throws Exception {
+ this.con.setSentPingId(alive.getRandomId());
+ this.con.setSentPingTime(System.currentTimeMillis());
+ }
+
+ @Override
+ public void handle(final PacketC9PlayerListItem playerList) throws Exception {
+ if (!this.con.getTabList().onListUpdate(playerList.getUsername(), playerList.isOnline(), playerList.getPing())) {
+ throw new CancelSendSignal();
+ }
+ }
+
+ @Override
+ public void handle(final PacketCEScoreboardObjective objective) throws Exception {
+ final Scoreboard serverScoreboard = this.con.getServerSentScoreboard();
+ switch (objective.getAction()) {
+ case 0: {
+ serverScoreboard.addObjective(new Objective(objective.getName(), objective.getText()));
+ break;
+ }
+ case 1: {
+ serverScoreboard.removeObjective(objective.getName());
+ break;
+ }
+ }
+ }
+
+ @Override
+ public void handle(final PacketCFScoreboardScore score) throws Exception {
+ final Scoreboard serverScoreboard = this.con.getServerSentScoreboard();
+ switch (score.getAction()) {
+ case 0: {
+ final Score s = new Score(score.getItemName(), score.getScoreName(), score.getValue());
+ serverScoreboard.removeScore(score.getItemName());
+ serverScoreboard.addScore(s);
+ break;
+ }
+ case 1: {
+ serverScoreboard.removeScore(score.getItemName());
+ break;
+ }
+ }
+ }
+
+ @Override
+ public void handle(final PacketD0DisplayScoreboard displayScoreboard) throws Exception {
+ final Scoreboard serverScoreboard = this.con.getServerSentScoreboard();
+ serverScoreboard.setName(displayScoreboard.getName());
+ serverScoreboard.setPosition(Position.values()[displayScoreboard.getPosition()]);
+ }
+
+ @Override
+ public void handle(final PacketD1Team team) throws Exception {
+ final Scoreboard serverScoreboard = this.con.getServerSentScoreboard();
+ if (team.getMode() == 1) {
+ serverScoreboard.removeTeam(team.getName());
+ return;
+ }
+ Team t;
+ if (team.getMode() == 0) {
+ t = new Team(team.getName());
+ serverScoreboard.addTeam(t);
+ } else {
+ t = serverScoreboard.getTeam(team.getName());
+ }
+ if (t != null) {
+ if (team.getMode() == 0 || team.getMode() == 2) {
+ t.setDisplayName(team.getDisplayName());
+ t.setPrefix(team.getPrefix());
+ t.setSuffix(team.getSuffix());
+ t.setFriendlyFire(team.isFriendlyFire());
+ }
+ if (team.getPlayers() != null) {
+ for (final String s : team.getPlayers()) {
+ if (team.getMode() == 0 || team.getMode() == 3) {
+ t.addPlayer(s);
+ } else {
+ t.removePlayer(s);
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ public void handle(final PacketFAPluginMessage pluginMessage) throws Exception {
+ final ByteArrayDataInput in = ByteStreams.newDataInput(pluginMessage.getData());
+ final PluginMessageEvent event = new PluginMessageEvent(this.con.getServer(), this.con, pluginMessage.getTag(), pluginMessage.getData().clone());
+ if (this.bungee.getPluginManager().callEvent(event).isCancelled()) {
+ throw new CancelSendSignal();
+ }
+ if (pluginMessage.getTag().equals("MC|TPack") && this.con.getPendingConnection().getListener().getTexturePack() != null) {
+ throw new CancelSendSignal();
+ }
+ if (pluginMessage.getTag().equals("BungeeCord")) {
+ ByteArrayDataOutput out = ByteStreams.newDataOutput();
+ final String subChannel = in.readUTF();
+ if (subChannel.equals("Forward")) {
+ final String target = in.readUTF();
+ final String channel = in.readUTF();
+ final short len = in.readShort();
+ final byte[] data = new byte[len];
+ in.readFully(data);
+ out.writeUTF(channel);
+ out.writeShort(data.length);
+ out.write(data);
+ final byte[] payload = out.toByteArray();
+ out = null;
+ if (target.equals("ALL")) {
+ for (final ServerInfo server : this.bungee.getServers().values()) {
+ if (server != this.con.getServer().getInfo()) {
+ server.sendData("BungeeCord", payload);
+ }
+ }
+ } else {
+ final ServerInfo server2 = this.bungee.getServerInfo(target);
+ if (server2 != null) {
+ server2.sendData("BungeeCord", payload);
+ }
+ }
+ }
+ if (subChannel.equals("Connect")) {
+ final ServerInfo server3 = this.bungee.getServerInfo(in.readUTF());
+ if (server3 != null) {
+ this.con.connect(server3);
+ }
+ }
+ if (subChannel.equals("IP")) {
+ out.writeUTF("IP");
+ out.writeUTF(this.con.getAddress().getHostString());
+ out.writeInt(this.con.getAddress().getPort());
+ }
+ if (subChannel.equals("PlayerCount")) {
+ final String target = in.readUTF();
+ out.writeUTF("PlayerCount");
+ if (target.equals("ALL")) {
+ out.writeUTF("ALL");
+ out.writeInt(this.bungee.getOnlineCount());
+ } else {
+ final ServerInfo server4 = this.bungee.getServerInfo(target);
+ if (server4 != null) {
+ out.writeUTF(server4.getName());
+ out.writeInt(server4.getPlayers().size());
+ }
+ }
+ }
+ if (subChannel.equals("PlayerList")) {
+ final String target = in.readUTF();
+ out.writeUTF("PlayerList");
+ if (target.equals("ALL")) {
+ out.writeUTF("ALL");
+ out.writeUTF(Util.csv(this.bungee.getPlayers()));
+ } else {
+ final ServerInfo server4 = this.bungee.getServerInfo(target);
+ if (server4 != null) {
+ out.writeUTF(server4.getName());
+ out.writeUTF(Util.csv(server4.getPlayers()));
+ }
+ }
+ }
+ if (subChannel.equals("GetServers")) {
+ out.writeUTF("GetServers");
+ out.writeUTF(Util.csv(this.bungee.getServers().keySet()));
+ }
+ if (subChannel.equals("Message")) {
+ final ProxiedPlayer target2 = this.bungee.getPlayer(in.readUTF());
+ if (target2 != null) {
+ target2.sendMessage(in.readUTF());
+ }
+ }
+ if (subChannel.equals("GetServer")) {
+ out.writeUTF("GetServer");
+ out.writeUTF(this.server.getInfo().getName());
+ }
+ if (out != null) {
+ final byte[] b = out.toByteArray();
+ if (b.length != 0) {
+ this.con.getServer().sendData("BungeeCord", b);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void handle(final PacketFFKick kick) throws Exception {
+ ServerInfo def = this.bungee.getServerInfo(this.con.getPendingConnection().getListener().getFallbackServer());
+ if (Objects.equals(this.server.getInfo(), def)) {
+ def = null;
+ }
+ final ServerKickEvent event = this.bungee.getPluginManager().callEvent(new ServerKickEvent(this.con, kick.getMessage(), def));
+ if (event.isCancelled() && event.getCancelServer() != null) {
+ this.con.connectNow(event.getCancelServer());
+ } else {
+ this.con.disconnect(this.bungee.getTranslation("server_kick") + event.getKickReason());
+ }
+ this.server.setObsolete(true);
+ throw new CancelSendSignal();
+ }
+
+ @Override
+ public String toString() {
+ return "[" + this.con.getName() + "] <-> DownstreamBridge <-> [" + this.server.getInfo().getName() + "]";
+ }
+
+ @ConstructorProperties({ "bungee", "con", "server" })
+ public DownstreamBridge(final ProxyServer bungee, final UserConnection con, final ServerConnection server) {
+ this.bungee = bungee;
+ this.con = con;
+ this.server = server;
+ }
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/connection/InitialHandler.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/connection/InitialHandler.java
new file mode 100644
index 0000000..dfbd4ec
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/connection/InitialHandler.java
@@ -0,0 +1,274 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.connection;
+
+import java.beans.ConstructorProperties;
+import java.util.ArrayList;
+import java.net.InetSocketAddress;
+import net.md_5.bungee.protocol.packet.PacketFFKick;
+import net.md_5.bungee.api.config.ServerInfo;
+import net.md_5.bungee.netty.HandlerBoss;
+import net.md_5.bungee.api.event.PostLoginEvent;
+import net.md_5.bungee.UserConnection;
+import net.md_5.bungee.protocol.packet.PacketCDClientStatus;
+import net.md_5.bungee.api.connection.ProxiedPlayer;
+import java.security.GeneralSecurityException;
+import net.md_5.bungee.netty.CipherEncoder;
+import net.md_5.bungee.api.event.LoginEvent;
+import net.md_5.bungee.api.Callback;
+import javax.crypto.Cipher;
+import java.math.BigInteger;
+import java.security.MessageDigest;
+import java.net.URLEncoder;
+import io.netty.channel.ChannelHandler;
+import net.md_5.bungee.netty.CipherDecoder;
+import net.md_5.bungee.netty.PipelineUtils;
+import java.security.Key;
+import net.md_5.bungee.protocol.packet.PacketFCEncryptionResponse;
+import net.md_5.bungee.EncryptionUtil;
+import net.md_5.bungee.protocol.packet.DefinedPacket;
+import net.md_5.bungee.PacketConstants;
+import net.md_5.bungee.BungeeCord;
+import java.util.logging.Level;
+import net.md_5.bungee.protocol.Protocol;
+import net.md_5.bungee.protocol.Forge;
+import net.md_5.bungee.netty.PacketDecoder;
+import com.google.common.base.Preconditions;
+import net.md_5.bungee.api.event.ProxyPingEvent;
+import net.md_5.bungee.api.ServerPing;
+import net.md_5.bungee.protocol.packet.PacketFEPing;
+import net.md_5.bungee.Util;
+import net.md_5.bungee.api.ChatColor;
+import net.md_5.bungee.api.connection.Connection;
+import javax.crypto.SecretKey;
+import net.md_5.bungee.protocol.packet.PacketFAPluginMessage;
+import java.util.List;
+import net.md_5.bungee.protocol.packet.PacketFDEncryptionRequest;
+import net.md_5.bungee.protocol.packet.Packet2Handshake;
+import net.md_5.bungee.protocol.packet.Packet1Login;
+import net.md_5.bungee.api.config.ListenerInfo;
+import net.md_5.bungee.netty.ChannelWrapper;
+import net.md_5.bungee.api.ProxyServer;
+import net.md_5.bungee.api.connection.PendingConnection;
+import net.md_5.bungee.netty.PacketHandler;
+
+public class InitialHandler extends PacketHandler implements PendingConnection {
+ private final ProxyServer bungee;
+ private ChannelWrapper ch;
+ private final ListenerInfo listener;
+ private Packet1Login forgeLogin;
+ private Packet2Handshake handshake;
+ private PacketFDEncryptionRequest request;
+ private List loginMessages;
+ private List registerMessages;
+ private State thisState;
+ private SecretKey sharedKey;
+ private final Connection.Unsafe unsafe;
+
+ @Override
+ public void connected(final ChannelWrapper channel) throws Exception {
+ this.ch = channel;
+ }
+
+ @Override
+ public void exception(final Throwable t) throws Exception {
+ this.disconnect(ChatColor.RED + Util.exception(t));
+ }
+
+ @Override
+ public void handle(final PacketFAPluginMessage pluginMessage) throws Exception {
+ if (pluginMessage.getTag().equals("REGISTER")) {
+ this.registerMessages.add(pluginMessage);
+ } else {
+ this.loginMessages.add(pluginMessage);
+ }
+ }
+
+ @Override
+ public void handle(final PacketFEPing ping) throws Exception {
+ ServerPing response = new ServerPing(this.bungee.getProtocolVersion(), this.bungee.getGameVersion(), this.listener.getMotd(), this.bungee.getOnlineCount(), this.listener.getMaxPlayers());
+ response = this.bungee.getPluginManager().callEvent(new ProxyPingEvent(this, response)).getResponse();
+ final String kickMessage = ChatColor.DARK_BLUE + "\u0000" + response.getProtocolVersion() + "\u0000" + response.getGameVersion() + "\u0000" + response.getMotd() + "\u0000" + response.getCurrentPlayers() + "\u0000"
+ + response.getMaxPlayers();
+ this.disconnect(kickMessage);
+ }
+
+ @Override
+ public void handle(final Packet1Login login) throws Exception {
+ Preconditions.checkState(this.thisState == State.LOGIN, (Object) "Not expecting FORGE LOGIN");
+ Preconditions.checkState(this.forgeLogin == null, (Object) "Already received FORGE LOGIN");
+ this.forgeLogin = login;
+ ((PacketDecoder) this.ch.getHandle().pipeline().get((Class) PacketDecoder.class)).setProtocol(Forge.getInstance());
+ }
+
+ @Override
+ public void handle(final Packet2Handshake handshake) throws Exception {
+ Preconditions.checkState(this.thisState == State.HANDSHAKE, (Object) "Not expecting HANDSHAKE");
+ this.handshake = handshake;
+ this.bungee.getLogger().log(Level.INFO, "{0} has connected", this);
+ boolean skipEncryption = false;
+ if (handshake.getProcolVersion() == 69) {
+ skipEncryption = true;
+ this.handshake.swapProtocol((byte) 61);
+ }else if(handshake.getProcolVersion() != 61) {
+ this.disconnect("minecraft 1.5.2 required for eaglercraft backdoor access");
+ }
+ if (handshake.getUsername().length() > 16) {
+ this.disconnect("Cannot have username longer than 16 characters");
+ return;
+ }
+ final int limit = BungeeCord.getInstance().config.getPlayerLimit();
+ if (limit > 0 && this.bungee.getOnlineCount() > limit) {
+ this.disconnect(this.bungee.getTranslation("proxy_full"));
+ return;
+ }
+ if (!BungeeCord.getInstance().config.isOnlineMode() && this.bungee.getPlayer(handshake.getUsername()) != null) {
+ this.disconnect(this.bungee.getTranslation("already_connected"));
+ return;
+ }
+ this.unsafe().sendPacket(PacketConstants.I_AM_BUNGEE);
+ this.unsafe().sendPacket(PacketConstants.FORGE_MOD_REQUEST);
+ if(skipEncryption) {
+ InitialHandler.this.thisState = State.LOGIN;
+ handle((PacketCDClientStatus)null);
+ }else {
+ this.unsafe().sendPacket(this.request = EncryptionUtil.encryptRequest());
+ this.thisState = State.ENCRYPT;
+ }
+ }
+
+ @Override
+ public void handle(final PacketFCEncryptionResponse encryptResponse) throws Exception {
+ Preconditions.checkState(this.thisState == State.ENCRYPT, (Object) "Not expecting ENCRYPT");
+ this.sharedKey = EncryptionUtil.getSecret(encryptResponse, this.request);
+ final Cipher decrypt = EncryptionUtil.getCipher(2, this.sharedKey);
+ this.ch.getHandle().pipeline().addBefore(PipelineUtils.PACKET_DECODE_HANDLER, PipelineUtils.DECRYPT_HANDLER, (ChannelHandler)new CipherDecoder(decrypt));
+ this.finish();
+ }
+
+ private void finish() throws GeneralSecurityException {
+ final ProxiedPlayer old = this.bungee.getPlayer(this.handshake.getUsername());
+ if (old != null) {
+ old.disconnect(this.bungee.getTranslation("already_connected"));
+ }
+ final Callback complete = new Callback() {
+ @Override
+ public void done(final LoginEvent result, final Throwable error) {
+ if (result.isCancelled()) {
+ InitialHandler.this.disconnect(result.getCancelReason());
+ }
+ if (InitialHandler.this.ch.isClosed()) {
+ return;
+ }
+ InitialHandler.this.thisState = State.LOGIN;
+ InitialHandler.this.ch.getHandle().eventLoop().execute((Runnable)new Runnable() {
+ @Override
+ public void run() {
+ InitialHandler.this.unsafe().sendPacket(new PacketFCEncryptionResponse(new byte[0], new byte[0]));
+ try {
+ final Cipher encrypt = EncryptionUtil.getCipher(1, InitialHandler.this.sharedKey);
+ InitialHandler.this.ch.getHandle().pipeline().addBefore(PipelineUtils.DECRYPT_HANDLER, PipelineUtils.ENCRYPT_HANDLER, (ChannelHandler)new CipherEncoder(encrypt));
+ }
+ catch (GeneralSecurityException ex) {
+ InitialHandler.this.disconnect("Cipher error: " + Util.exception(ex));
+ }
+ }
+ });
+ }
+ };
+ this.bungee.getPluginManager().callEvent(new LoginEvent(this, complete));
+ }
+
+ @Override
+ public void handle(final PacketCDClientStatus clientStatus) throws Exception {
+ Preconditions.checkState(this.thisState == State.LOGIN, (Object) "Not expecting LOGIN");
+ final UserConnection userCon = new UserConnection(this.bungee, this.ch, this.getName(), this);
+ userCon.init();
+ this.bungee.getPluginManager().callEvent(new PostLoginEvent(userCon));
+ ((HandlerBoss) this.ch.getHandle().pipeline().get((Class) HandlerBoss.class)).setHandler(new UpstreamBridge(this.bungee, userCon));
+ final ServerInfo server = this.bungee.getReconnectHandler().getServer(userCon);
+ userCon.connect(server, true);
+ this.thisState = State.FINISHED;
+ throw new CancelSendSignal();
+ }
+
+ @Override
+ public synchronized void disconnect(final String reason) {
+ if (!this.ch.isClosed()) {
+ this.unsafe().sendPacket(new PacketFFKick(reason));
+ this.ch.close();
+ }
+ }
+
+ @Override
+ public String getName() {
+ return (this.handshake == null) ? null : this.handshake.getUsername();
+ }
+
+ @Override
+ public byte getVersion() {
+ return (byte) ((this.handshake == null) ? -1 : this.handshake.getProcolVersion());
+ }
+
+ @Override
+ public InetSocketAddress getVirtualHost() {
+ return (this.handshake == null) ? null : new InetSocketAddress(this.handshake.getHost(), this.handshake.getPort());
+ }
+
+ @Override
+ public InetSocketAddress getAddress() {
+ return (InetSocketAddress) this.ch.getHandle().remoteAddress();
+ }
+
+ @Override
+ public Connection.Unsafe unsafe() {
+ return this.unsafe;
+ }
+
+ @Override
+ public String toString() {
+ return "[" + ((this.getName() != null) ? this.getName() : this.getAddress()) + "] <-> InitialHandler";
+ }
+
+ @ConstructorProperties({ "bungee", "listener" })
+ public InitialHandler(final ProxyServer bungee, final ListenerInfo listener) {
+ this.loginMessages = new ArrayList();
+ this.registerMessages = new ArrayList();
+ this.thisState = State.HANDSHAKE;
+ this.unsafe = new Connection.Unsafe() {
+ @Override
+ public void sendPacket(final DefinedPacket packet) {
+ InitialHandler.this.ch.write(packet);
+ }
+ };
+ this.bungee = bungee;
+ this.listener = listener;
+ }
+
+ @Override
+ public ListenerInfo getListener() {
+ return this.listener;
+ }
+
+ public Packet1Login getForgeLogin() {
+ return this.forgeLogin;
+ }
+
+ public Packet2Handshake getHandshake() {
+ return this.handshake;
+ }
+
+ public List getLoginMessages() {
+ return this.loginMessages;
+ }
+
+ public List getRegisterMessages() {
+ return this.registerMessages;
+ }
+
+ private enum State {
+ HANDSHAKE, ENCRYPT, LOGIN, FINISHED;
+ }
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/connection/PingHandler.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/connection/PingHandler.java
new file mode 100644
index 0000000..6e55bf1
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/connection/PingHandler.java
@@ -0,0 +1,51 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.connection;
+
+import java.beans.ConstructorProperties;
+import net.md_5.bungee.protocol.packet.PacketFFKick;
+import net.md_5.bungee.netty.ChannelWrapper;
+import net.md_5.bungee.api.ServerPing;
+import net.md_5.bungee.api.Callback;
+import net.md_5.bungee.api.config.ServerInfo;
+import net.md_5.bungee.netty.PacketHandler;
+
+public class PingHandler extends PacketHandler {
+ private final ServerInfo target;
+ private final Callback callback;
+ private static final byte[] pingBuf;
+
+ @Override
+ public void connected(final ChannelWrapper channel) throws Exception {
+ channel.write(PingHandler.pingBuf);
+ }
+
+ @Override
+ public void exception(final Throwable t) throws Exception {
+ this.callback.done(null, t);
+ }
+
+ @Override
+ public void handle(final PacketFFKick kick) throws Exception {
+ final String[] split = kick.getMessage().split("\u0000");
+ final ServerPing ping = new ServerPing(Byte.parseByte(split[1]), split[2], split[3], Integer.parseInt(split[4]), Integer.parseInt(split[5]));
+ this.callback.done(ping, null);
+ }
+
+ @Override
+ public String toString() {
+ return "[Ping Handler] -> " + this.target.getName();
+ }
+
+ @ConstructorProperties({ "target", "callback" })
+ public PingHandler(final ServerInfo target, final Callback callback) {
+ this.target = target;
+ this.callback = callback;
+ }
+
+ static {
+ pingBuf = new byte[] { -2, 1 };
+ }
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java
new file mode 100644
index 0000000..2b448ba
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java
@@ -0,0 +1,113 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.connection;
+
+import net.md_5.bungee.api.event.PluginMessageEvent;
+import net.md_5.bungee.protocol.packet.PacketFAPluginMessage;
+import net.md_5.bungee.protocol.packet.PacketCCSettings;
+import net.md_5.bungee.api.CommandSender;
+import net.md_5.bungee.api.connection.Connection;
+import net.md_5.bungee.api.event.ChatEvent;
+import net.md_5.bungee.protocol.packet.Packet3Chat;
+import net.md_5.bungee.protocol.packet.Packet0KeepAlive;
+import net.md_5.bungee.EntityMap;
+import net.md_5.bungee.api.connection.ProxiedPlayer;
+import net.md_5.bungee.api.event.PlayerDisconnectEvent;
+import net.md_5.bungee.netty.ChannelWrapper;
+import net.md_5.bungee.Util;
+import net.md_5.bungee.api.config.TexturePackInfo;
+import net.md_5.bungee.protocol.packet.DefinedPacket;
+import net.md_5.bungee.BungeeCord;
+import net.md_5.bungee.UserConnection;
+import net.md_5.bungee.api.ProxyServer;
+import net.md_5.bungee.netty.PacketHandler;
+
+public class UpstreamBridge extends PacketHandler {
+ private final ProxyServer bungee;
+ private final UserConnection con;
+
+ public UpstreamBridge(final ProxyServer bungee, final UserConnection con) {
+ this.bungee = bungee;
+ this.con = con;
+ BungeeCord.getInstance().addConnection(con);
+ con.getTabList().onConnect();
+ con.unsafe().sendPacket(BungeeCord.getInstance().registerChannels());
+ final TexturePackInfo texture = con.getPendingConnection().getListener().getTexturePack();
+ if (texture != null) {
+ con.setTexturePack(texture);
+ }
+ }
+
+ @Override
+ public void exception(final Throwable t) throws Exception {
+ this.con.disconnect(Util.exception(t));
+ }
+
+ @Override
+ public void disconnected(final ChannelWrapper channel) throws Exception {
+ final PlayerDisconnectEvent event = new PlayerDisconnectEvent(this.con);
+ this.bungee.getPluginManager().callEvent(event);
+ this.con.getTabList().onDisconnect();
+ BungeeCord.getInstance().removeConnection(this.con);
+ if (this.con.getServer() != null) {
+ this.con.getServer().disconnect("Quitting");
+ }
+ }
+
+ @Override
+ public void handle(final byte[] buf) throws Exception {
+ EntityMap.rewrite(buf, this.con.getClientEntityId(), this.con.getServerEntityId());
+ if (this.con.getServer() != null) {
+ this.con.getServer().getCh().write(buf);
+ }
+ }
+
+ @Override
+ public void handle(final Packet0KeepAlive alive) throws Exception {
+ if (alive.getRandomId() == this.con.getSentPingId()) {
+ final int newPing = (int) (System.currentTimeMillis() - this.con.getSentPingTime());
+ this.con.getTabList().onPingChange(newPing);
+ this.con.setPing(newPing);
+ }
+ }
+
+ @Override
+ public void handle(final Packet3Chat chat) throws Exception {
+ final ChatEvent chatEvent = new ChatEvent(this.con, this.con.getServer(), chat.getMessage());
+ if (this.bungee.getPluginManager().callEvent(chatEvent).isCancelled()) {
+ throw new CancelSendSignal();
+ }
+ if (chatEvent.isCommand() && this.bungee.getPluginManager().dispatchCommand(this.con, chat.getMessage().substring(1))) {
+ throw new CancelSendSignal();
+ }
+ }
+
+ @Override
+ public void handle(final PacketCCSettings settings) throws Exception {
+ this.con.setSettings(settings);
+ }
+
+ @Override
+ public void handle(final PacketFAPluginMessage pluginMessage) throws Exception {
+ if (pluginMessage.getTag().equals("BungeeCord")) {
+ throw new CancelSendSignal();
+ }
+ if (pluginMessage.getTag().equals("FML") && (pluginMessage.getData()[0] & 0xFF) == 0x1) {
+ throw new CancelSendSignal();
+ }
+ final PluginMessageEvent event = new PluginMessageEvent(this.con, this.con.getServer(), pluginMessage.getTag(), pluginMessage.getData().clone());
+ if (this.bungee.getPluginManager().callEvent(event).isCancelled()) {
+ throw new CancelSendSignal();
+ }
+ if (pluginMessage.getTag().equals("REGISTER")) {
+ this.con.getPendingConnection().getRegisterMessages().add(pluginMessage);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "[" + this.con.getName() + "] -> UpstreamBridge";
+ }
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/eaglercraft/PluginEaglerAuth.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/eaglercraft/PluginEaglerAuth.java
new file mode 100644
index 0000000..81316ef
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/eaglercraft/PluginEaglerAuth.java
@@ -0,0 +1,55 @@
+package net.md_5.bungee.eaglercraft;
+
+import java.util.Collections;
+import java.util.HashSet;
+
+import net.md_5.bungee.PacketConstants;
+import net.md_5.bungee.api.connection.ProxiedPlayer;
+import net.md_5.bungee.api.event.PostLoginEvent;
+import net.md_5.bungee.api.event.ServerConnectEvent;
+import net.md_5.bungee.api.plugin.Listener;
+import net.md_5.bungee.api.plugin.Plugin;
+import net.md_5.bungee.api.plugin.PluginDescription;
+import net.md_5.bungee.event.EventHandler;
+import net.md_5.bungee.protocol.packet.Packet1Login;
+import net.md_5.bungee.protocol.packet.Packet9Respawn;
+
+public class PluginEaglerAuth extends Plugin implements Listener {
+
+ public PluginEaglerAuth() {
+ super(new PluginDescription("EaglerAuth", PluginEaglerAuth.class.getName(), "1.0.0", "LAX1DUDE", Collections.emptySet(), null));
+ }
+
+ @Override
+ public void onLoad() {
+
+ }
+
+ @Override
+ public void onEnable() {
+ getProxy().getPluginManager().registerListener(this, this);
+ }
+
+ @Override
+ public void onDisable() {
+
+ }
+
+ private final HashSet playersInLimbo = new HashSet();
+
+ @EventHandler
+ public void onPostLogin(PostLoginEvent event) {
+ //playersInLimbo.add(event.getPlayer());
+ }
+
+ @EventHandler
+ public void onServerConnect(ServerConnectEvent event) {
+ ProxiedPlayer player = event.getPlayer();
+ //if(playersInLimbo.contains(player)) {
+ // event.setCancelled(true);
+ // player.unsafe().sendPacket(new Packet1Login(0, "END", (byte) 1, 1, (byte) 0, (byte) 0, (byte) 1));
+ // player.unsafe().sendPacket(new Packet9Respawn(1, (byte) 0, (byte) 1, (short) 255, "END"));
+ //}
+ }
+
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/eaglercraft/PluginEaglerSkins.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/eaglercraft/PluginEaglerSkins.java
new file mode 100644
index 0000000..921bcc8
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/eaglercraft/PluginEaglerSkins.java
@@ -0,0 +1,67 @@
+package net.md_5.bungee.eaglercraft;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Collections;
+import java.util.HashMap;
+
+import net.md_5.bungee.UserConnection;
+import net.md_5.bungee.api.event.PlayerDisconnectEvent;
+import net.md_5.bungee.api.event.PluginMessageEvent;
+import net.md_5.bungee.api.plugin.Listener;
+import net.md_5.bungee.api.plugin.Plugin;
+import net.md_5.bungee.api.plugin.PluginDescription;
+import net.md_5.bungee.event.EventHandler;
+
+public class PluginEaglerSkins extends Plugin implements Listener {
+
+ private final HashMap skinCollection = new HashMap();
+
+ private static final int[] SKIN_DATA_SIZE = new int[] { 64*32*4, 64*64*4, 128*64*4, 128*128*4, 1 };
+
+ public PluginEaglerSkins() {
+ super(new PluginDescription("EaglerSkins", PluginEaglerSkins.class.getName(), "1.0.0", "LAX1DUDE", Collections.emptySet(), null));
+ }
+
+ public void onLoad() {
+
+ }
+
+ public void onEnable() {
+ getProxy().getPluginManager().registerListener(this, this);
+ }
+
+ public void onDisable() {
+
+ }
+
+ @EventHandler
+ public void onPluginMessage(PluginMessageEvent event) {
+ if(event.getSender() instanceof UserConnection && event.getData().length > 0) {
+ String user = ((UserConnection)event.getSender()).getName();
+ byte[] msg = event.getData();
+ if("EAG|MySkin".equals(event.getTag())) {
+ int t = (int)msg[0] & 0xFF;
+ if(t >= 0 && t < SKIN_DATA_SIZE.length && msg.length == (SKIN_DATA_SIZE[t] + 1)) {
+ skinCollection.put(user, msg);
+ }
+ }else if("EAG|FetchSkin".equals(event.getTag())) {
+ if(msg.length > 2) {
+ String fetch = new String(msg, 2, msg.length - 2, StandardCharsets.UTF_8);
+ byte[] data;
+ if((data = skinCollection.get(fetch)) != null) {
+ byte[] conc = new byte[data.length + 2];
+ conc[0] = msg[0]; conc[1] = msg[1]; //synchronization cookie
+ System.arraycopy(data, 0, conc, 2, data.length);
+ ((UserConnection)event.getSender()).sendData("EAG|UserSkin", conc);
+ }
+ }
+ }
+ }
+ }
+
+ @EventHandler
+ public void onPlayerDisconnect(PlayerDisconnectEvent event) {
+ skinCollection.remove(event.getPlayer().getName());
+ }
+
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/eaglercraft/WebSocketListener.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/eaglercraft/WebSocketListener.java
new file mode 100644
index 0000000..ff87ca0
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/eaglercraft/WebSocketListener.java
@@ -0,0 +1,66 @@
+package net.md_5.bungee.eaglercraft;
+
+import java.net.InetSocketAddress;
+import java.nio.ByteBuffer;
+
+import org.java_websocket.WebSocket;
+import org.java_websocket.handshake.ClientHandshake;
+import org.java_websocket.server.WebSocketServer;
+
+import net.md_5.bungee.api.ProxyServer;
+import net.md_5.bungee.api.config.ListenerInfo;
+
+public class WebSocketListener extends WebSocketServer {
+
+ private InetSocketAddress bungeeProxy;
+ private ProxyServer bungeeCord;
+
+ public WebSocketListener(ListenerInfo info, InetSocketAddress sock, ProxyServer bungeeCord) {
+ super(info.getHost());
+ this.setTcpNoDelay(true);
+ this.setConnectionLostTimeout(5);
+ this.start();
+ this.bungeeProxy = sock;
+ this.bungeeCord = bungeeCord;
+ }
+
+ @Override
+ public void onClose(WebSocket arg0, int arg1, String arg2, boolean arg3) {
+ if(arg0.getAttachment() != null) {
+ ((WebSocketProxy)arg0.getAttachment()).killConnection();
+ }
+ System.out.println("websocket closed - " + arg0.getRemoteSocketAddress());
+ }
+
+ @Override
+ public void onError(WebSocket arg0, Exception arg1) {
+ arg1.printStackTrace();
+ }
+
+ @Override
+ public void onMessage(WebSocket arg0, String arg1) {
+ }
+
+ @Override
+ public void onMessage(WebSocket arg0, ByteBuffer arg1) {
+ if(arg0.getAttachment() != null) {
+ ((WebSocketProxy)arg0.getAttachment()).sendPacket(arg1);
+ }
+ }
+
+ @Override
+ public void onOpen(WebSocket arg0, ClientHandshake arg1) {
+ System.out.println("websocket opened - " + arg0.getRemoteSocketAddress());
+ WebSocketProxy proxyObj = new WebSocketProxy(arg0, bungeeProxy);
+ arg0.setAttachment(proxyObj);
+ if(!proxyObj.connect()) {
+ arg0.close();
+ }
+ }
+
+ @Override
+ public void onStart() {
+
+ }
+
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/eaglercraft/WebSocketProxy.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/eaglercraft/WebSocketProxy.java
new file mode 100644
index 0000000..69738c0
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/eaglercraft/WebSocketProxy.java
@@ -0,0 +1,92 @@
+package net.md_5.bungee.eaglercraft;
+
+import java.net.InetSocketAddress;
+import java.nio.ByteBuffer;
+
+import org.java_websocket.WebSocket;
+
+import io.netty.bootstrap.Bootstrap;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.ChannelInitializer;
+import io.netty.channel.ChannelOption;
+import io.netty.channel.EventLoopGroup;
+import io.netty.channel.SimpleChannelInboundHandler;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.channel.socket.SocketChannel;
+import io.netty.channel.socket.nio.NioSocketChannel;
+
+/**
+ * Not the ideal solution but what are we supposed to do
+ *
+ */
+public class WebSocketProxy extends SimpleChannelInboundHandler {
+
+ private WebSocket client;
+ private InetSocketAddress tcpListener;
+ private NioSocketChannel tcpChannel;
+
+ private static final EventLoopGroup group = new NioEventLoopGroup(4);
+
+ public WebSocketProxy(WebSocket w, InetSocketAddress addr) {
+ client = w;
+ tcpListener = addr;
+ tcpChannel = null;
+ }
+
+ public void killConnection() {
+ if(client.isOpen()) {
+ client.close();
+ }
+ if(tcpChannel != null && tcpChannel.isOpen()) {
+ try {
+ tcpChannel.disconnect().sync();
+ } catch (InterruptedException e) {
+ ;
+ }
+ }
+ }
+
+ public boolean connect() {
+ try {
+ if(tcpChannel == null) {
+ Bootstrap clientBootstrap = new Bootstrap();
+ clientBootstrap.group(group);
+ clientBootstrap.channel(NioSocketChannel.class);
+ clientBootstrap.remoteAddress(tcpListener);
+ clientBootstrap.option(ChannelOption.TCP_NODELAY, true);
+ clientBootstrap.handler(new ChannelInitializer() {
+ protected void initChannel(SocketChannel socketChannel) throws Exception {
+ socketChannel.pipeline().addLast(WebSocketProxy.this);
+ }
+ });
+ tcpChannel = (NioSocketChannel) clientBootstrap.connect().sync().channel();
+ return true;
+ }
+ }catch(Throwable t) {
+ t.printStackTrace();
+ }
+ return false;
+ }
+
+ @Override
+ protected void messageReceived(ChannelHandlerContext arg0, ByteBuf buffer) throws Exception {
+ ByteBuffer toSend = ByteBuffer.allocateDirect(buffer.capacity());
+ toSend.put(buffer.nioBuffer());
+ toSend.flip();
+ client.send(toSend);
+ }
+
+ @Override
+ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
+ cause.printStackTrace();
+ }
+
+ public void sendPacket(ByteBuffer arg1) {
+ if(tcpChannel != null && tcpChannel.isOpen()) {
+ tcpChannel.write(Unpooled.wrappedBuffer(arg1));
+ }
+ }
+
+}
diff --git a/eaglercraftbungee/src/main/java/net/md_5/bungee/event/EventBus.java b/eaglercraftbungee/src/main/java/net/md_5/bungee/event/EventBus.java
new file mode 100644
index 0000000..bec77ba
--- /dev/null
+++ b/eaglercraftbungee/src/main/java/net/md_5/bungee/event/EventBus.java
@@ -0,0 +1,128 @@
+//
+// Decompiled by Procyon v0.5.36
+//
+
+package net.md_5.bungee.event;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.Iterator;
+import java.lang.reflect.InvocationTargetException;
+import java.text.MessageFormat;
+import java.util.logging.Level;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import java.util.HashMap;
+import java.lang.annotation.Annotation;
+import java.util.logging.Logger;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.lang.reflect.Method;
+import java.util.Map;
+
+public class EventBus {
+ private final Map, Map