Start a hugely messy implementation of the API

This commit is contained in:
md_5 2013-01-16 11:16:21 +11:00
parent 8c942e299f
commit 098ca5920e
30 changed files with 275 additions and 690 deletions

View File

@ -97,4 +97,14 @@ public abstract class ProxyServer
* @param adapter the adapter to use
*/
public abstract void setConfigurationAdapter(ConfigurationAdapter adapter);
/**
* Gracefully mark this instance for shutdown.
*/
public abstract void stop();
/**
* Start this instance so that it may accept connections.
*/
public abstract void start();
}

View File

@ -27,6 +27,13 @@ public abstract class ProxiedPlayer implements Connection, CommandSender
*/
public abstract void connect(Server server);
/**
* Gets the server this player is connected to.
*
* @return the server this player is connected to
*/
public abstract Server getServer();
/**
* Gets the ping time between the proxy and this connection.
*

View File

@ -17,6 +17,16 @@ public abstract class Command
private final String permission;
private final String[] aliases;
/**
* Construct a new command with no permissions or aliases.
*
* @param name the name of this command
*/
public Command(String name)
{
this(name, null);
}
/**
* Construct a new command.
*

View File

@ -6,17 +6,26 @@ import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Timer;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.logging.Level;
import java.util.logging.Logger;
import lombok.Getter;
import static net.md_5.bungee.Logger.$;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.config.ConfigurationAdapter;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.connection.Server;
import net.md_5.bungee.api.plugin.PluginManager;
import net.md_5.bungee.command.*;
import net.md_5.bungee.packet.DefinedPacket;
import net.md_5.bungee.packet.PacketFAPluginMessage;
@ -29,7 +38,7 @@ import net.md_5.bungee.tablist.TabListHandler;
/**
* Main BungeeCord proxy class.
*/
public class BungeeCord
public class BungeeCord extends ProxyServer
{
/**
@ -40,10 +49,6 @@ public class BungeeCord
* Server game version.
*/
public static final String GAME_VERSION = "1.4.6";
/**
* Current software instance.
*/
public static BungeeCord instance;
/**
* Current operation state.
*/
@ -59,7 +64,7 @@ public class BungeeCord
/**
* locations.yml save thread.
*/
private final ReconnectSaveThread saveThread = new ReconnectSaveThread();
private final Timer saveThread = new Timer("Reconnect Saver");
/**
* Server socket listener.
*/
@ -88,18 +93,20 @@ public class BungeeCord
/**
* Plugin manager.
*/
public final JavaPluginManager pluginManager = new JavaPluginManager();
@Getter
public final PluginManager pluginManager = new PluginManager();
{
commandMap.put("greload", new CommandReload());
commandMap.put("end", new CommandEnd());
commandMap.put("glist", new CommandList());
commandMap.put("server", new CommandServer());
commandMap.put("ip", new CommandIP());
commandMap.put("alert", new CommandAlert());
commandMap.put("motd", new CommandMotd());
commandMap.put("bungee", new CommandBungee());
getPluginManager().registerCommand(new CommandReload());
getPluginManager().registerCommand(new CommandReload());
getPluginManager().registerCommand(new CommandEnd());
getPluginManager().registerCommand(new CommandList());
getPluginManager().registerCommand(new CommandServer());
getPluginManager().registerCommand(new CommandIP());
getPluginManager().registerCommand(new CommandAlert());
getPluginManager().registerCommand(new CommandMotd());
getPluginManager().registerCommand(new CommandBungee());
}
/**
@ -110,17 +117,18 @@ public class BungeeCord
*/
public static void main(String[] args) throws IOException
{
instance = new BungeeCord();
$().info("Enabled BungeeCord version " + instance.version);
instance.start();
BungeeCord bungee = new BungeeCord();
ProxyServer.setInstance(bungee);
$().info("Enabled BungeeCord version " + bungee.getVersion());
bungee.start();
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
while (instance.isRunning)
while (bungee.isRunning)
{
String line = br.readLine();
if (line != null)
{
boolean handled = instance.dispatchCommand(line, ConsoleCommandSender.instance);
boolean handled = getInstance().getPluginManager().dispatchCommand(ConsoleCommandSender.instance, line);
if (!handled)
{
System.err.println("Command not found");
@ -338,4 +346,52 @@ public class BungeeCord
globalPluginChannels.add(channel);
broadcast(new PacketFAPluginMessage("REGISTER", channel.getBytes()));
}
@Override
public String getName()
{
return "BungeeCord";
}
@Override
public String getVersion()
{
return version;
}
@Override
public Logger getLogger()
{
return $();
}
@Override
public Collection<ProxiedPlayer> getPlayers()
{
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public ProxiedPlayer getPlayer(String name)
{
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public Server getServer(String name)
{
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public Collection<Server> getServers()
{
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public void setConfigurationAdapter(ConfigurationAdapter adapter)
{
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
}

View File

@ -1,18 +0,0 @@
package net.md_5.bungee;
public enum Permission
{
/**
* Can access all commands.
*/
ADMIN,
/**
* Can access commands which do not affect everyone.
*/
MODERATOR,
/**
* Can access other commands.
*/
DEFAULT;
}

View File

@ -1,30 +0,0 @@
package net.md_5.bungee;
/**
* Class to call the {@link Configuration#saveHosts() } method at 5 minute
* intervals.
*/
public class ReconnectSaveThread extends Thread
{
public ReconnectSaveThread()
{
super("Location Save Thread");
setPriority(Thread.MIN_PRIORITY);
}
@Override
public void run()
{
while (BungeeCord.instance.isRunning)
{
try
{
Thread.sleep(5 * 1000 * 60); // 5 minutes
} catch (InterruptedException ex)
{
}
BungeeCord.instance.config.saveHosts();
}
}
}

View File

@ -1,26 +0,0 @@
package net.md_5.bungee.command;
import net.md_5.bungee.BungeeCord;
import net.md_5.bungee.Permission;
/**
* Class which represents a proxy command. The {@link #execute(net.md_5.bungee.command.CommandSender, java.lang.String[])
* } method will be called to dispatch the command.
*/
public abstract class Command
{
/**
* Execute this command.
*
* @param sender the sender executing this command
* @param args the parameters to this command, does not include the '/' or
* the original command.
*/
public abstract void execute(CommandSender sender, String[] args);
public Permission getPermission(CommandSender sender)
{
return BungeeCord.instance.config.getPermission(sender);
}
}

View File

@ -1,21 +1,22 @@
package net.md_5.bungee.command;
import net.md_5.bungee.BungeeCord;
import net.md_5.bungee.Permission;
import net.md_5.bungee.UserConnection;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.plugin.Command;
public class CommandAlert extends Command
{
public CommandAlert()
{
super("alert", "bungee.command.alert");
}
@Override
public void execute(CommandSender sender, String[] args)
{
if (getPermission(sender) != Permission.ADMIN)
{
sender.sendMessage(ChatColor.RED + "You do not have permission to execute this command!");
return;
}
if (args.length == 0)
{
sender.sendMessage(ChatColor.RED + "You must supply a message.");
@ -36,9 +37,9 @@ public class CommandAlert extends Command
}
String message = builder.substring(0, builder.length() - 1);
for (UserConnection con : BungeeCord.instance.connections.values())
for (ProxiedPlayer player : ProxyServer.getInstance().getPlayers())
{
con.sendMessage(message);
player.sendMessage(message);
}
}
}

View File

@ -2,14 +2,20 @@ package net.md_5.bungee.command;
import net.md_5.bungee.BungeeCord;
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(CommandSender sender, String[] args)
{
sender.sendMessage(ChatColor.BLUE + "This server is running BungeeCord version " + BungeeCord.version + " by md_5");
sender.sendMessage(ChatColor.BLUE + "Your current permission level is " + getPermission(sender).name());
}
}

View File

@ -1,8 +1,8 @@
package net.md_5.bungee.command;
import net.md_5.bungee.BungeeCord;
import net.md_5.bungee.Permission;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.plugin.Command;
/**
* Command to terminate the proxy instance. May only be used by the console.
@ -10,15 +10,14 @@ import net.md_5.bungee.api.ChatColor;
public class CommandEnd extends Command
{
public CommandEnd()
{
super("end", "bungeecord.command.end");
}
@Override
public void execute(CommandSender sender, String[] args)
{
if (getPermission(sender) != Permission.ADMIN)
{
sender.sendMessage(ChatColor.RED + "You do not have permission to use this command");
} else
{
BungeeCord.instance.stop();
}
BungeeCord.getInstance().stop();
}
}

View File

@ -1,27 +1,28 @@
package net.md_5.bungee.command;
import net.md_5.bungee.BungeeCord;
import net.md_5.bungee.Permission;
import net.md_5.bungee.UserConnection;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.plugin.Command;
public class CommandIP extends Command
{
public CommandIP()
{
super("ip", "bungeecord.command.ip");
}
@Override
public void execute(CommandSender sender, String[] args)
{
if (getPermission(sender) != Permission.MODERATOR && getPermission(sender) != Permission.ADMIN)
{
sender.sendMessage(ChatColor.RED + "You do not have permission to use this command");
return;
}
if (args.length < 1)
{
sender.sendMessage(ChatColor.RED + "Please follow this command by a user name");
return;
}
UserConnection user = BungeeCord.instance.connections.get(args[0]);
ProxiedPlayer user = ProxyServer.getInstance().getPlayer(args[0]);
if (user == null)
{
sender.sendMessage(ChatColor.RED + "That user is not online");

View File

@ -1,9 +1,11 @@
package net.md_5.bungee.command;
import java.util.Collection;
import net.md_5.bungee.BungeeCord;
import net.md_5.bungee.UserConnection;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.plugin.Command;
/**
* Command to list all players connected to the proxy.
@ -11,11 +13,16 @@ import net.md_5.bungee.api.ChatColor;
public class CommandList extends Command
{
public CommandList()
{
super("list", "bungeecord.command.list");
}
@Override
public void execute(CommandSender sender, String[] args)
{
StringBuilder users = new StringBuilder();
Collection<UserConnection> connections = BungeeCord.instance.connections.values();
Collection<ProxiedPlayer> connections = ProxyServer.getInstance().getPlayers();
if (connections.isEmpty())
{
@ -23,18 +30,9 @@ public class CommandList extends Command
return;
}
for (UserConnection con : connections)
for (ProxiedPlayer player : connections)
{
switch (getPermission(con))
{
case ADMIN:
users.append(ChatColor.RED);
break;
case MODERATOR:
users.append(ChatColor.GREEN);
break;
}
users.append(con.username);
users.append(player.getDisplayName());
users.append(", ");
users.append(ChatColor.RESET);
}

View File

@ -1,8 +1,10 @@
package net.md_5.bungee.command;
import net.md_5.bungee.BungeeCord;
import net.md_5.bungee.Permission;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.plugin.Command;
/**
* Command to set a temp copy of the motd in real-time without stopping the
@ -11,21 +13,20 @@ import net.md_5.bungee.api.ChatColor;
public class CommandMotd extends Command
{
public CommandMotd()
{
super("bungeecord.command.motd");
}
@Override
public void execute(CommandSender sender, String[] args)
{
if (getPermission(sender) != Permission.ADMIN)
{
sender.sendMessage(ChatColor.RED + "You do not have permission to use this command");
} else
{
String newMOTD = "";
StringBuilder newMOTD = new StringBuilder();
for (String s : args)
{
newMOTD = newMOTD + s + " ";
}
newMOTD = newMOTD.substring(0, newMOTD.length() - 1);
BungeeCord.instance.config.motd = ChatColor.translateAlternateColorCodes('&', newMOTD);
newMOTD.append(s);
newMOTD.append(" ");
}
((BungeeCord) ProxyServer.getInstance()).config.motd = ChatColor.translateAlternateColorCodes('&', newMOTD.substring(0, newMOTD.length() - 1));
}
}

View File

@ -1,21 +1,23 @@
package net.md_5.bungee.command;
import net.md_5.bungee.BungeeCord;
import net.md_5.bungee.Permission;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.plugin.Command;
public class CommandReload extends Command
{
public CommandReload()
{
super("greload", "bungeecord.command.reload");
}
@Override
public void execute(CommandSender sender, String[] args)
{
if (getPermission(sender) != Permission.ADMIN)
{
sender.sendMessage(ChatColor.RED + "You do not have permission to execute this command!");
return;
}
BungeeCord.instance.config.load();
((BungeeCord) ProxyServer.getInstance()).config.load();
sender.sendMessage(ChatColor.GREEN + "Reloaded config, please restart if you have any issues");
}
}

View File

@ -1,19 +0,0 @@
package net.md_5.bungee.command;
public interface CommandSender
{
/**
* Sends a message to the client at the earliest available opportunity.
*
* @param message the message to send
*/
public abstract void sendMessage(String message);
/**
* Get the senders name or CONSOLE for console.
*
* @return the friendly name of the player.
*/
public abstract String getName();
}

View File

@ -4,6 +4,11 @@ import java.util.Collection;
import net.md_5.bungee.BungeeCord;
import net.md_5.bungee.UserConnection;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.connection.Server;
import net.md_5.bungee.api.plugin.Command;
/**
* Command to list and switch a player between available servers.
@ -11,37 +16,42 @@ import net.md_5.bungee.api.ChatColor;
public class CommandServer extends Command
{
public CommandServer()
{
super("server", "bungeecord.command.server");
}
@Override
public void execute(CommandSender sender, String[] args)
{
if (!(sender instanceof UserConnection))
if (!(sender instanceof ProxiedPlayer))
{
return;
}
UserConnection con = (UserConnection) sender;
Collection<String> servers = BungeeCord.instance.config.servers.keySet();
if (args.length <= 0)
ProxiedPlayer player = (ProxiedPlayer) sender;
Collection<Server> servers = ProxyServer.getInstance().getServers();
if (args.length == 0)
{
StringBuilder serverList = new StringBuilder();
for (String server : servers)
for (Server server : servers)
{
serverList.append(server);
serverList.append(server.getInfo().getName());
serverList.append(", ");
}
serverList.setLength(serverList.length() - 2);
con.sendMessage(ChatColor.GOLD + "You may connect to the following servers at this time: " + serverList.toString());
player.sendMessage(ChatColor.GOLD + "You may connect to the following servers at this time: " + serverList.toString());
} else
{
String server = args[0];
if (!servers.contains(server))
Server server = ProxyServer.getInstance().getServer(args[0]);
if (server == null)
{
con.sendMessage(ChatColor.RED + "The specified server does not exist");
} else if (args[0].equals(con.getServer()))
player.sendMessage(ChatColor.RED + "The specified server does not exist");
} else if (server == player.getServer())
{
con.sendMessage(ChatColor.RED + "You are already on this server.");
player.sendMessage(ChatColor.RED + "You are already on this server.");
} else
{
con.connect(server);
player.connect(server);
}
}
}

View File

@ -1,6 +1,9 @@
package net.md_5.bungee.command;
import java.util.Collection;
import java.util.Collections;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.CommandSender;
/**
* Command sender representing the proxy console.
@ -21,4 +24,34 @@ public class ConsoleCommandSender implements CommandSender
{
return "CONSOLE";
}
@Override
public Collection<String> getGroups()
{
return Collections.emptySet();
}
@Override
public void addGroups(String... groups)
{
throw new UnsupportedOperationException("Console may not have groups");
}
@Override
public void removeGroups(String... groups)
{
throw new UnsupportedOperationException("Console may not have groups");
}
@Override
public boolean hasPermission(String permission)
{
return true;
}
@Override
public void setPermission(String permission, boolean value)
{
throw new UnsupportedOperationException("Console has all permissions");
}
}

View File

@ -1,22 +0,0 @@
package net.md_5.bungee.plugin;
/**
* An event which may be canceled and this be prevented from happening.
*/
public interface Cancellable
{
/**
* Sets the canceled state of this event.
*
* @param canceled whether this event is canceled or not
*/
public void setCancelled(boolean canceled);
/**
* Gets the canceled state of this event.
*
* @return whether this event is canceled or not
*/
public boolean isCancelled();
}

View File

@ -1,36 +0,0 @@
package net.md_5.bungee.plugin;
import lombok.Data;
import net.md_5.bungee.UserConnection;
@Data
public class ChatEvent implements Cancellable
{
/**
* Canceled state.
*/
private boolean cancelled;
/**
* Whether this packet is destined for the server or the client.
*/
private final Destination destination;
/**
* User in question.
*/
private final UserConnection connection;
/**
* Text contained in this chat.
*/
private String text;
/**
* An enum that signifies the destination for this packet.
*/
public enum Destination
{
SERVER,
CLIENT
}
}

View File

@ -1,20 +0,0 @@
package net.md_5.bungee.plugin;
/**
* Exception thrown when a plugin could not be loaded for any reason.
*/
public class InvalidPluginException extends RuntimeException
{
private static final long serialVersionUID = 1L;
public InvalidPluginException(String message, Throwable cause)
{
super(message, cause);
}
public InvalidPluginException(String message)
{
super(message);
}
}

View File

@ -1,75 +0,0 @@
package net.md_5.bungee.plugin;
import net.md_5.bungee.BungeeCord;
import net.md_5.bungee.command.Command;
/**
* Base class which all proxy plugins should extend.
*/
public abstract class JavaPlugin
{
/**
* Description file.
*/
PluginDescription description;
/**
* Called on enable.
*/
public void onEnable()
{
}
/**
* Called on disable.
*/
public void onDisable()
{
}
/**
* Called when a user connects with their name and address. To keep things
* simple this name has not been checked with minecraft.net.
*/
public void onHandshake(LoginEvent event)
{
}
/**
* Called after a user has been authed with minecraftt.net and is about to
* log into the proxy.
*/
public void onLogin(LoginEvent event)
{
}
/**
* Called when a user is connecting to a new server.
*/
public void onServerConnect(ServerConnectEvent event)
{
}
/**
* Called when a plugin message is sent to the client or server
*/
public void onPluginMessage(PluginMessageEvent event)
{
}
/**
* Called when a chat message is sent to the client or server
*/
public void onChat(ChatEvent event)
{
}
/**
* Register a command for use with the proxy.
*/
protected final void registerCommand(String label, Command command)
{
BungeeCord.instance.commandMap.put(label, command);
}
}

View File

@ -1,127 +0,0 @@
package net.md_5.bungee.plugin;
import com.google.common.io.PatternFilenameFilter;
import java.io.File;
import java.io.InputStream;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.HashSet;
import java.util.Set;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;
import lombok.Getter;
import static net.md_5.bungee.Logger.$;
/**
* Plugin manager to handle loading and saving other JavaPlugin's. This class is
* itself a plugin for ease of use.
*/
public class JavaPluginManager extends JavaPlugin
{
/**
* Set of loaded plugins.
*/
@Getter
private final Set<JavaPlugin> plugins = new HashSet<>();
/**
* Load all plugins from the plugins folder. This method must only be called
* once per instance.
*/
public void loadPlugins()
{
File dir = new File("plugins");
dir.mkdir();
for (File file : dir.listFiles(new PatternFilenameFilter(".*\\.jar")))
{
try
{
JarFile jar = new JarFile(file);
ZipEntry entry = jar.getEntry("plugin.yml");
if (entry == null)
{
throw new InvalidPluginException("Jar does not contain a plugin.yml");
}
PluginDescription description;
try (InputStream is = jar.getInputStream(entry))
{
description = PluginDescription.load(is);
}
URLClassLoader classloader = new URLClassLoader(new URL[]
{
file.toURI().toURL()
}, getClass().getClassLoader());
Class<?> clazz = Class.forName(description.getMain(), true, classloader);
Class<? extends JavaPlugin> subClazz = clazz.asSubclass(JavaPlugin.class);
JavaPlugin plugin = subClazz.getDeclaredConstructor().newInstance();
plugin.description = description;
plugin.onEnable();
plugins.add(plugin);
$().info("Loaded plugin: " + plugin.description.getName());
} catch (Exception ex)
{
$().severe("Could not load plugin: " + file);
ex.printStackTrace();
}
}
}
@Override
public void onDisable()
{
for (JavaPlugin p : plugins)
{
p.onDisable();
}
}
@Override
public void onHandshake(LoginEvent event)
{
for (JavaPlugin p : plugins)
{
p.onHandshake(event);
}
}
@Override
public void onLogin(LoginEvent event)
{
for (JavaPlugin p : plugins)
{
p.onLogin(event);
}
}
@Override
public void onServerConnect(ServerConnectEvent event)
{
for (JavaPlugin p : plugins)
{
p.onServerConnect(event);
}
}
@Override
public void onPluginMessage(PluginMessageEvent event)
{
for (JavaPlugin p : plugins)
{
p.onPluginMessage(event);
}
}
@Override
public void onChat(ChatEvent event)
{
for (JavaPlugin p : plugins)
{
p.onChat(event);
}
}
}

View File

@ -1,33 +0,0 @@
package net.md_5.bungee.plugin;
import java.net.InetAddress;
import lombok.Data;
/**
* Event called to represent a player logging in.
*/
@Data
public class LoginEvent implements Cancellable
{
/**
* Canceled state.
*/
private boolean cancelled;
/**
* Message to use when kicking if this event is canceled.
*/
private String cancelReason;
/**
* Username which the player wishes to use.
*/
private final String username;
/**
* IP address of the remote connection.
*/
private final InetAddress address;
/**
* Hostname which the user tried to connect to.
*/
private final String hostname;
}

View File

@ -1,48 +0,0 @@
package net.md_5.bungee.plugin;
import java.io.InputStream;
import java.lang.reflect.Field;
import lombok.Data;
import org.yaml.snakeyaml.Yaml;
/**
* File which contains information about a plugin, its authors, and how to load
* it.
*/
@Data
public class PluginDescription
{
private String name;
private String main;
private String version;
private String author;
private PluginDescription()
{
}
public static PluginDescription load(InputStream is)
{
PluginDescription ret = new Yaml().loadAs(is, PluginDescription.class);
if (ret == null)
{
throw new InvalidPluginException("Could not load plugin description file.");
}
for (Field f : PluginDescription.class.getDeclaredFields())
{
try
{
if (f.get(ret) == null)
{
throw new InvalidPluginException(f.getName() + " is not set properly in plugin description");
}
} catch (IllegalArgumentException | IllegalAccessException ex)
{
}
}
return ret;
}
}

View File

@ -1,47 +0,0 @@
package net.md_5.bungee.plugin;
import lombok.Data;
import net.md_5.bungee.UserConnection;
/**
* Event called when a plugin message is sent to the client or server
*/
@Data
public class PluginMessageEvent implements Cancellable
{
/**
* Canceled state.
*/
private boolean cancelled;
/**
* Message to use when kicking if this event is canceled.
*/
private String cancelReason;
/**
* Whether this packet is destined for the server or the client
*/
private final Destination destination;
/**
* User in question
*/
private final UserConnection connection;
/**
* Tag specified for this plugin message.
*/
private String tag;
/**
* Data contained in this plugin message.
*/
private String data;
/**
* An enum that signifies the destination for this packet
*/
public enum Destination
{
SERVER,
CLIENT
}
}

View File

@ -1,33 +0,0 @@
package net.md_5.bungee.plugin;
import lombok.Data;
import net.md_5.bungee.UserConnection;
/**
* Event called when the decision is made to decide which server to connect to.
*/
@Data
public class ServerConnectEvent
{
/**
* If the player currently has no server, this is true
*/
private final boolean firstTime;
/**
* Message to send just before the change. null for no message
*/
private String message;
/**
* User in question.
*/
private final UserConnection connection;
/**
* Name of the server they are connecting to.
*/
private final String server;
/**
* Name of the server which they will be forwarded to instead.
*/
private String newServer;
}

View File

@ -4,23 +4,23 @@ import java.util.Collections;
import java.util.Map;
import java.util.WeakHashMap;
import net.md_5.bungee.BungeeCord;
import net.md_5.bungee.UserConnection;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.packet.PacketC9PlayerListItem;
public class GlobalPingTabList extends GlobalTabList
{
public static final int PING_THRESHOLD = 20;
private Map<UserConnection, Integer> lastPings = Collections.synchronizedMap(new WeakHashMap<UserConnection, Integer>());
private Map<ProxiedPlayer, Integer> lastPings = Collections.synchronizedMap(new WeakHashMap<ProxiedPlayer, Integer>());
@Override
public void onPingChange(final UserConnection con, final int ping)
public void onPingChange(ProxiedPlayer player, int ping)
{
Integer lastPing = lastPings.get(con);
Integer lastPing = lastPings.get(player);
if (lastPing == null || (ping - PING_THRESHOLD > lastPing && ping + PING_THRESHOLD < lastPing))
{
BungeeCord.instance.broadcast(new PacketC9PlayerListItem(con.tabListName, true, ping));
lastPings.put(con, ping);
BungeeCord.instance.broadcast(new PacketC9PlayerListItem(player.getDisplayName(), true, ping));
lastPings.put(player, ping);
}
}
}

View File

@ -5,15 +5,17 @@ import java.util.HashSet;
import java.util.Set;
import net.md_5.bungee.BungeeCord;
import net.md_5.bungee.UserConnection;
import net.md_5.bungee.api.TabListHandler;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.packet.PacketC9PlayerListItem;
public class GlobalTabList implements TabListHandler
{
private Set<UserConnection> sentPings = Collections.synchronizedSet(new HashSet<UserConnection>());
private Set<ProxiedPlayer> sentPings = Collections.synchronizedSet(new HashSet<ProxiedPlayer>());
@Override
public void onJoin(UserConnection con)
public void onConnect(ProxiedPlayer player)
{
for (UserConnection c : BungeeCord.instance.connections.values())
{
@ -22,29 +24,29 @@ public class GlobalTabList implements TabListHandler
}
@Override
public void onServerChange(UserConnection con)
public void onPingChange(ProxiedPlayer player, int ping)
{
}
@Override
public void onPingChange(final UserConnection con, final int ping)
if (!sentPings.contains(player))
{
if (!sentPings.contains(con))
{
BungeeCord.instance.broadcast(new PacketC9PlayerListItem(con.tabListName, true, con.getPing()));
sentPings.add(con);
BungeeCord.instance.broadcast(new PacketC9PlayerListItem(player.getDisplayName(), true, player.getPing()));
sentPings.add(player);
}
}
@Override
public void onDisconnect(final UserConnection con)
public void onDisconnect(ProxiedPlayer player)
{
BungeeCord.instance.broadcast(new PacketC9PlayerListItem(con.tabListName, false, 9999));
sentPings.remove(con);
BungeeCord.instance.broadcast(new PacketC9PlayerListItem(player.getDisplayName(), false, 9999));
sentPings.remove(player);
}
@Override
public boolean onPacketC9(UserConnection con, PacketC9PlayerListItem packet)
public void onServerChange(ProxiedPlayer player)
{
}
@Override
public boolean onListUpdate(ProxiedPlayer player, String name, boolean online, int ping)
{
return false;
}

View File

@ -5,30 +5,41 @@ import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
import net.md_5.bungee.UserConnection;
import net.md_5.bungee.api.TabListHandler;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.packet.PacketC9PlayerListItem;
public class ServerUniqueTabList implements TabListHandler
{
private Map<UserConnection, Set<String>> sentUsernames = Collections.synchronizedMap(new WeakHashMap<UserConnection, Set<String>>());
private Map<ProxiedPlayer, Set<String>> sentUsernames = Collections.synchronizedMap(new WeakHashMap<ProxiedPlayer, Set<String>>());
@Override
public void onJoin(UserConnection con)
public void onConnect(ProxiedPlayer player)
{
}
@Override
public void onServerChange(UserConnection con)
public void onPingChange(ProxiedPlayer player, int ping)
{
Set<String> usernames = sentUsernames.get(con);
}
@Override
public void onDisconnect(ProxiedPlayer player)
{
}
@Override
public void onServerChange(ProxiedPlayer player)
{
Set<String> usernames = sentUsernames.get(player);
if (usernames != null)
{
synchronized (usernames)
{
for (String username : usernames)
{
con.packetQueue.add(new PacketC9PlayerListItem(username, false, 9999));
player.packetQueue.add(new PacketC9PlayerListItem(username, false, 9999));
}
usernames.clear();
}
@ -36,31 +47,21 @@ public class ServerUniqueTabList implements TabListHandler
}
@Override
public void onPingChange(UserConnection con, int ping)
public boolean onListUpdate(ProxiedPlayer player, String name, boolean online, int ping)
{
}
@Override
public void onDisconnect(UserConnection con)
{
}
@Override
public boolean onPacketC9(final UserConnection con, final PacketC9PlayerListItem packet)
{
Set<String> usernames = sentUsernames.get(con);
Set<String> usernames = sentUsernames.get(player);
if (usernames == null)
{
usernames = new LinkedHashSet<>();
sentUsernames.put(con, usernames);
sentUsernames.put(player, usernames);
}
if (packet.online)
if (online)
{
usernames.add(packet.username);
usernames.add(name);
} else
{
usernames.remove(packet.username);
usernames.remove(name);
}
return true;

View File

@ -1,18 +0,0 @@
package net.md_5.bungee.tablist;
import net.md_5.bungee.UserConnection;
import net.md_5.bungee.packet.PacketC9PlayerListItem;
public interface TabListHandler
{
public void onJoin(UserConnection con);
public void onServerChange(UserConnection con);
public void onPingChange(UserConnection con, int ping);
public void onDisconnect(UserConnection con);
public boolean onPacketC9(UserConnection con, PacketC9PlayerListItem packet);
}