Add basic api with connect event

This commit is contained in:
md_5 2012-10-06 09:00:26 +10:00
parent 01cf90a8ba
commit c5097e234a
8 changed files with 193 additions and 1 deletions

View File

@ -18,6 +18,7 @@ import net.md_5.bungee.command.CommandList;
import net.md_5.bungee.command.CommandSender;
import net.md_5.bungee.command.CommandServer;
import net.md_5.bungee.command.ConsoleCommandSender;
import net.md_5.bungee.plugin.JavaPluginManager;
public class BungeeCord {
@ -56,7 +57,11 @@ public class BungeeCord {
/**
* Registered commands.
*/
private Map<String, Command> commandMap = new HashMap<>();
public Map<String, Command> commandMap = new HashMap<>();
/**
* Plugin manager.
*/
public final JavaPluginManager pluginManager = new JavaPluginManager();
{
commandMap.put("end", new CommandEnd());
@ -105,6 +110,8 @@ public class BungeeCord {
config.load();
isRunning = true;
pluginManager.loadPlugins();
InetSocketAddress addr = Util.getAddr(config.bindHost);
listener = new ListenThread(addr);
listener.start();
@ -115,6 +122,8 @@ public class BungeeCord {
public void stop() {
this.isRunning = false;
$().info("Disabling plugin");
pluginManager.onDisable();
$().info("Closing listen thread");
try {

View File

@ -9,6 +9,7 @@ import net.md_5.bungee.packet.PacketFCEncryptionResponse;
import net.md_5.bungee.packet.PacketFDEncryptionRequest;
import net.md_5.bungee.packet.PacketFFKick;
import net.md_5.bungee.packet.PacketInputStream;
import net.md_5.bungee.plugin.ConnectEvent;
import org.bouncycastle.crypto.io.CipherInputStream;
import org.bouncycastle.crypto.io.CipherOutputStream;
@ -32,6 +33,13 @@ public class InitialHandler implements Runnable {
switch (id) {
case 0x02:
Packet2Handshake handshake = new Packet2Handshake(packet);
// fire connect event
ConnectEvent event = new ConnectEvent(handshake.username, socket.getInetAddress());
BungeeCord.instance.pluginManager.onConnect(event);
if (event.isCancelled()) {
throw new KickException(event.getCancelReason());
}
PacketFDEncryptionRequest request = EncryptionUtil.encryptRequest();
out.write(request.getPacket());
PacketFCEncryptionResponse response = new PacketFCEncryptionResponse(in.readPacket());

View File

@ -0,0 +1,8 @@
package net.md_5.bungee.plugin;
public interface Cancellable {
public void setCancelled(boolean cancelled);
public boolean isCancelled();
}

View File

@ -0,0 +1,13 @@
package net.md_5.bungee.plugin;
import java.net.InetAddress;
import lombok.Data;
@Data
public class ConnectEvent implements Cancellable {
private boolean cancelled;
private String cancelReason;
private final String username;
private final InetAddress address;
}

View File

@ -0,0 +1,14 @@
package net.md_5.bungee.plugin;
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

@ -0,0 +1,38 @@
package net.md_5.bungee.plugin;
import net.md_5.bungee.BungeeCord;
import net.md_5.bungee.command.Command;
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 onConnect(ConnectEvent event) {
}
/**
* Register a command.
*/
protected void registerCommand(String label, Command command) {
BungeeCord.instance.commandMap.put(label, command);
}
}

View File

@ -0,0 +1,66 @@
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.$;
public class JavaPluginManager extends JavaPlugin {
@Getter
private final Set<JavaPlugin> plugins = new HashSet<>();
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 onConnect(ConnectEvent event) {
for (JavaPlugin p : plugins) {
p.onConnect(event);
}
}
}

View File

@ -0,0 +1,36 @@
package net.md_5.bungee.plugin;
import java.io.InputStream;
import java.lang.reflect.Field;
import lombok.Data;
import org.yaml.snakeyaml.Yaml;
@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;
}
}