diff --git a/src/main/java/cn/nukkit/Server.java b/src/main/java/cn/nukkit/Server.java index b1138654b63..9549df6bdec 100644 --- a/src/main/java/cn/nukkit/Server.java +++ b/src/main/java/cn/nukkit/Server.java @@ -598,24 +598,14 @@ public int broadcastMessage(TextContainer message, Collection recipients = new HashSet<>(); - - for (String permission : permissions.split(";")) { - for (Permissible permissible : this.pluginManager.getPermissionSubscriptions(permission)) { - if (permissible instanceof CommandSender && permissible.hasPermission(permission)) { - recipients.add((CommandSender) permissible); - } - } - } - - for (CommandSender recipient : recipients) { - recipient.sendMessage(message); - } - - return recipients.size(); + return broadcast((Object) message,permissions); } public int broadcast(TextContainer message, String permissions) { + return broadcast((Object) message,permissions); + } + + private int broadcast(Object message,String permissions){ Set recipients = new HashSet<>(); for (String permission : permissions.split(";")) { @@ -627,7 +617,11 @@ public int broadcast(TextContainer message, String permissions) { } for (CommandSender recipient : recipients) { - recipient.sendMessage(message); + if(message instanceof String) { + recipient.sendMessage((String) message); + }else if(message instanceof TextContainer){ + recipient.sendMessage((TextContainer) message); + } } return recipients.size(); diff --git a/src/main/java/cn/nukkit/command/PluginCommand.java b/src/main/java/cn/nukkit/command/PluginCommand.java index 597ecedfb43..9387bb6e88d 100644 --- a/src/main/java/cn/nukkit/command/PluginCommand.java +++ b/src/main/java/cn/nukkit/command/PluginCommand.java @@ -9,9 +9,9 @@ */ public class PluginCommand extends Command implements PluginIdentifiableCommand { - private final T owningPlugin; + protected final T owningPlugin; - private CommandExecutor executor; + protected CommandExecutor executor; public PluginCommand(String name, T owner) { super(name); diff --git a/src/main/java/cn/nukkit/permission/Permission.java b/src/main/java/cn/nukkit/permission/Permission.java index 00039105b87..c67b6d57094 100644 --- a/src/main/java/cn/nukkit/permission/Permission.java +++ b/src/main/java/cn/nukkit/permission/Permission.java @@ -1,6 +1,7 @@ package cn.nukkit.permission; import cn.nukkit.Server; +import cn.nukkit.plugin.simple.Children; import java.util.*; @@ -130,6 +131,28 @@ public Permission addParent(String name, boolean value) { return perm; } + public static HashMap parsePermission(cn.nukkit.plugin.simple.Permission[] permissions){ + HashMap pers = new HashMap<>(); + for(cn.nukkit.plugin.simple.Permission p:permissions){ + HashMap pers_child = new HashMap<>(); + pers_child.put("description",p.description()); + pers_child.put("default",p.theDefault()); + Children[] children = p.childeren(); + if(children.length!=0) { + HashMap map = new HashMap<>(); + for (Children c : children) { + HashMap childValue = new HashMap<>(); + childValue.put("description",c.description()); + childValue.put("default",c.theDefault()); + map.put(c.name(),childValue); + } + pers_child.put("children",map); + } + pers.put(p.permission(),pers_child); + } + return pers; + } + public static List loadPermissions(Map data) { return loadPermissions(data, DEFAULT_OP); } diff --git a/src/main/java/cn/nukkit/plugin/JavaPluginLoader.java b/src/main/java/cn/nukkit/plugin/JavaPluginLoader.java index 8c1b7501567..e0e39f9cf6e 100644 --- a/src/main/java/cn/nukkit/plugin/JavaPluginLoader.java +++ b/src/main/java/cn/nukkit/plugin/JavaPluginLoader.java @@ -1,20 +1,24 @@ package cn.nukkit.plugin; import cn.nukkit.Server; +import cn.nukkit.event.Listener; import cn.nukkit.event.plugin.PluginDisableEvent; import cn.nukkit.event.plugin.PluginEnableEvent; +import cn.nukkit.plugin.simple.*; import cn.nukkit.utils.PluginException; import cn.nukkit.utils.Utils; import java.io.File; import java.io.IOException; import java.io.InputStream; -import java.util.HashMap; -import java.util.Map; +import java.lang.reflect.Field; +import java.util.*; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.regex.Pattern; +import static cn.nukkit.permission.Permission.parsePermission; + /** * Created by Nukkit Team. */ @@ -25,6 +29,10 @@ public class JavaPluginLoader implements PluginLoader { private final Map classes = new HashMap<>(); private final Map classLoaders = new HashMap<>(); + private final Map loadedSimplePlugin = new HashMap<>(); + + private final Map> simplePluginEnableClasses = new HashMap<>(); + public JavaPluginLoader(Server server) { this.server = server; } @@ -46,9 +54,7 @@ public Plugin loadPlugin(File file) throws Exception { try { Class javaClass = classLoader.loadClass(className); - if (!PluginBase.class.isAssignableFrom(javaClass)) { - throw new PluginException("Main class `" + description.getMain() + "' does not extend PluginBase"); - } + PluginAssert.isPluginBaseChild(javaClass,description.getMain()); try { Class pluginClass = (Class) javaClass.asSubclass(PluginBase.class); @@ -56,6 +62,7 @@ public Plugin loadPlugin(File file) throws Exception { plugin = pluginClass.newInstance(); this.initPlugin(plugin, description, dataFolder, file); + loadEnableRegister(new ArrayList<>(),plugin.getClass(),false,file,classLoader); return plugin; } catch (ClassCastException e) { throw new PluginException("Error whilst initializing main class `" + description.getMain() + "'", e); @@ -64,13 +71,177 @@ public Plugin loadPlugin(File file) throws Exception { } } catch (ClassNotFoundException e) { - throw new PluginException("Couldn't load plugin " + description.getName() + ": main class not found"); + PluginAssert.findMainClass(description.getName()); } } return null; } + //simple load Plugin + @Override + public Plugin simpleLoadPlugin(File file) { + try { + Class pluginClass = getSimplePlugin(file); + PluginDescription pluginDescription = getSimpleDescription(pluginClass); + this.server.getLogger().info(this.server.getLanguage().translateString("nukkit.plugin.load", pluginDescription.getFullName())); + File dataFolder = new File(file.getParentFile(), pluginDescription.getName()); + PluginBase plugin = (PluginBase) pluginClass.newInstance(); + this.initPlugin(plugin,pluginDescription,dataFolder,file); + return plugin; + }catch (InstantiationException | IllegalAccessException e){ + throw new PluginException(e.getMessage()); + } + //do it + } + + @Override + public Plugin simpleLoadPlugin(String fileName) { + return simpleLoadPlugin(new File(fileName)); + } + + private Class getSimplePlugin(File file){ + if(loadedSimplePlugin.containsKey(file)){ + return loadedSimplePlugin.get(file); + } + try(JarFile jarFile = new JarFile(file)){ + PluginClassLoader classLoader = new PluginClassLoader(this, this.getClass().getClassLoader(),file); + Enumeration entries = jarFile.entries(); + + List haveLoaded = new ArrayList<>(); + Class mainClass = null; + while (entries.hasMoreElements()){ + String name = entries.nextElement().getName(); + if(name.endsWith(".class")) { + String mainName = getClassName(name); + Class clz = classLoader.loadClass(mainName); + Main main = clz.getAnnotation(Main.class); + haveLoaded.add(clz); + if(main != null){ + classLoaders.put(main.name(),classLoader); + loadedSimplePlugin.put(file,clz); + PluginAssert.isPluginBaseChild(clz,mainName); + mainClass = clz; + } + } + } + + + if(mainClass!=null) { + loadEnableRegister(haveLoaded,mainClass,true,file,classLoader); + return mainClass; + } + PluginAssert.findMainClass(""); + }catch (IOException|ClassNotFoundException e){ + throw new PluginException(e.getMessage()); + } + return null; + } + + private void loadEnableRegister(List haveLoaded,Class mainClass,boolean hasLoaded,File file,PluginClassLoader loader){ + List> noRegister = null; + EnableRegister register = mainClass.getAnnotation(EnableRegister.class); + boolean isEnableRegister = register != null; + List classes = new ArrayList<>(); + simplePluginEnableClasses.put(mainClass, classes); + if (register != null) { + noRegister = Arrays.asList(register.noRegister()); + } + EnableCommand command = mainClass.getAnnotation(EnableCommand.class); + boolean isEnableCommand = command !=null; + List> noCommands = null; + if(command != null){ + noCommands = Arrays.asList(command.noRegister()); + } + if(isEnableCommand||isEnableRegister){ + if(!hasLoaded){ + try(JarFile jarFile = new JarFile(file)){ + Enumeration entries = jarFile.entries(); + while (entries.hasMoreElements()) { + String name = entries.nextElement().getName(); + if (name.endsWith(".class")) { + haveLoaded.add(loader.loadClass(getClassName(name))); + } + } + }catch (IOException|ClassNotFoundException e){ + throw new PluginException(e.getMessage()); + } + } + } + + for (Class loaded : haveLoaded) { + if(isEnableRegister){ + if (Arrays.asList(loaded.getInterfaces()).contains(Listener.class)) { + + if (!noRegister.contains(loaded)) { + simplePluginEnableClasses.get(mainClass).add(loaded); + } + } + } + if(isEnableCommand){ + if (cn.nukkit.command.Command.class.isAssignableFrom(loaded)) { + + if (!noCommands.contains(loaded)) { + simplePluginEnableClasses.get(mainClass).add(loaded); + } + } + } + + + } + + + } + + private String getClassName(String name){ + return name.substring(0, name.lastIndexOf(".")).replace("/", "."); + } + /** + * the simple description for simple plugin system + * @param plugin the main class + * @return the description for simple plugin system + */ + private PluginDescription getSimpleDescription(Class plugin){ + Main main = plugin.getAnnotation(Main.class); + if(main == null){ + return null; + } + String name = main.name(); + String version = main.version(); + String author = main.author(); + String description = main.description(); + PluginLoadOrder pluginLoadOrder = main.load(); + String website = main.website(); + String prefix = main.prefix(); + List api = Arrays.asList(main.api()); + List depend = Arrays.asList(main.depend()); + List loadBefore = Arrays.asList(main.loadBefore()); + List softDepend = Arrays.asList(main.softDepend()); + Map hashMap = new HashMap<>(); + hashMap.put("name",name); + hashMap.put("version",version); + hashMap.put("author",author); + hashMap.put("api",api); + hashMap.put("depend",depend); + hashMap.put("loadBefore",loadBefore); + hashMap.put("softDepend",softDepend); + hashMap.put("description",description); + hashMap.put("load",pluginLoadOrder.toString()); + hashMap.put("website",website); + hashMap.put("prefix",prefix.equals("")?name:prefix); + hashMap.put("main",plugin.getName()); + hashMap.put("isSimple",true); + PluginDescription descript = new PluginDescription(hashMap); + Permission[] permissions = main.permissions(); + hashMap.put("permissions",parsePermission(permissions)); + Command[] commands = main.commands(); + for(Command command:commands){ + descript.getCommands().put(command.name(),command); + } + return descript; + } + + @Override public Plugin loadPlugin(String filename) throws Exception { return this.loadPlugin(new File(filename)); @@ -83,6 +254,10 @@ public PluginDescription getPluginDescription(File file) { if (entry == null) { entry = jar.getJarEntry("plugin.yml"); if (entry == null) { + Class clz = getSimplePlugin(file); + if(clz != null){ + return getSimpleDescription(clz); + } return null; } } @@ -116,10 +291,39 @@ public void enablePlugin(Plugin plugin) { ((PluginBase) plugin).setEnabled(true); + try { + if (simplePluginEnableClasses.get(plugin.getClass())!=null) { + List assemblies = simplePluginEnableClasses.get(plugin.getClass()); + for (Class clz : assemblies) { + Object obj = clz.newInstance(); + autoPlugin(obj,plugin); + if(cn.nukkit.command.Command.class.isAssignableFrom(clz)){ + server.getCommandMap().register(plugin.getName(),(cn.nukkit.command.Command)obj); + }else{ + server.getPluginManager().registerEvents((Listener) obj, plugin); + } + + } + } + }catch (InstantiationException|IllegalAccessException e){ + throw new PluginException(e.getMessage()); + } + this.server.getPluginManager().callEvent(new PluginEnableEvent(plugin)); } } + private void autoPlugin(Object obj,Plugin plugin) throws IllegalAccessException{ + Class clz = obj.getClass(); + Field[] fields = clz.getDeclaredFields(); + for(Field field:fields){ + if(field.getAnnotation(AutoPlugin.class)!=null) { + field.setAccessible(true); + field.set(obj,plugin); + } + } + } + @Override public void disablePlugin(Plugin plugin) { if (plugin instanceof PluginBase && plugin.isEnabled()) { diff --git a/src/main/java/cn/nukkit/plugin/PluginAssert.java b/src/main/java/cn/nukkit/plugin/PluginAssert.java new file mode 100644 index 00000000000..1b83c08476f --- /dev/null +++ b/src/main/java/cn/nukkit/plugin/PluginAssert.java @@ -0,0 +1,16 @@ +package cn.nukkit.plugin; + +import cn.nukkit.utils.PluginException; + +public class PluginAssert { + + static void isPluginBaseChild(Class javaClass,String main){ + if (!PluginBase.class.isAssignableFrom(javaClass)) { + throw new PluginException("Main class `" + main + "' does not extend PluginBase"); + } + } + + static void findMainClass(String name) throws PluginException{ + throw new PluginException("Couldn't load plugin "+name+": main class not found"); + } +} diff --git a/src/main/java/cn/nukkit/plugin/PluginDescription.java b/src/main/java/cn/nukkit/plugin/PluginDescription.java index e62bc82c608..70d86547170 100644 --- a/src/main/java/cn/nukkit/plugin/PluginDescription.java +++ b/src/main/java/cn/nukkit/plugin/PluginDescription.java @@ -122,6 +122,7 @@ public class PluginDescription { private String website; private String prefix; private PluginLoadOrder order = PluginLoadOrder.POSTWORLD; + private boolean isSimple; private List permissions = new ArrayList<>(); @@ -204,6 +205,10 @@ private void loadMap(Map plugin) throws PluginException { if (plugin.containsKey("permissions")) { this.permissions = Permission.loadPermissions((Map) plugin.get("permissions")); } + if(plugin.containsKey("isSimple")){ + Boolean obj = (Boolean) plugin.get("isSimple"); + this.isSimple = obj==null?false:obj; + } } /** @@ -408,4 +413,13 @@ public String getVersion() { public String getWebsite() { return website; } + + /** + * the plugin use the simple plugin system,the isSimple will + * be true + * @return is it a Simple Plugin? + */ + public boolean isSimple() { + return isSimple; + } } diff --git a/src/main/java/cn/nukkit/plugin/PluginLoader.java b/src/main/java/cn/nukkit/plugin/PluginLoader.java index 4d36c55fbbf..44418314f53 100644 --- a/src/main/java/cn/nukkit/plugin/PluginLoader.java +++ b/src/main/java/cn/nukkit/plugin/PluginLoader.java @@ -58,6 +58,18 @@ public interface PluginLoader { */ Plugin loadPlugin(File file) throws Exception; + /** + * 一个简便开发的插件加载系统,基于原来的插件系统
+ * A simple plugin loading system based on the original plugin system + * @param file 这个插件的文件的 {@code File}对象。
A {@code File} object for this plugin. + * @return 加载完毕的插件的 {@code Plugin}对象。
The loaded plugin as a {@code Plugin} object. + * @see #loadPlugin(File) + * @since Nukkit 1.0 | Nukkit API 1.0.9 + */ + Plugin simpleLoadPlugin(File file); + + Plugin simpleLoadPlugin(String fileName); + /** * 通过插件文件名的字符串,来获得描述这个插件的 {@code PluginDescription}对象。
* Gets a {@code PluginDescription} object describes the plugin by its file name. @@ -135,4 +147,5 @@ public interface PluginLoader { */ void disablePlugin(Plugin plugin); + } diff --git a/src/main/java/cn/nukkit/plugin/PluginManager.java b/src/main/java/cn/nukkit/plugin/PluginManager.java index fab4bc5c7a1..fc674c35e6e 100644 --- a/src/main/java/cn/nukkit/plugin/PluginManager.java +++ b/src/main/java/cn/nukkit/plugin/PluginManager.java @@ -6,6 +6,8 @@ import cn.nukkit.event.*; import cn.nukkit.permission.Permissible; import cn.nukkit.permission.Permission; +import cn.nukkit.plugin.simple.Command; +import cn.nukkit.plugin.simple.SimplePluginCommand; import cn.nukkit.utils.MainLogger; import cn.nukkit.utils.PluginException; import cn.nukkit.utils.Utils; @@ -90,14 +92,15 @@ public Plugin loadPlugin(File file, Map loaders) { for (Pattern pattern : loader.getPluginFilters()) { if (pattern.matcher(file.getName()).matches()) { PluginDescription description = loader.getPluginDescription(file); - if (description != null) { + if (description != null&&!description.isSimple()) { try { Plugin plugin = loader.loadPlugin(file); if (plugin != null) { this.plugins.put(plugin.getDescription().getName(), plugin); List pluginCommands = this.parseYamlCommands(plugin); - + // simple command + pluginCommands.addAll(this.parseSimplePluginCommands(plugin)); if (!pluginCommands.isEmpty()) { this.commandMap.registerAll(plugin.getDescription().getName(), pluginCommands); } @@ -108,6 +111,14 @@ public Plugin loadPlugin(File file, Map loaders) { Server.getInstance().getLogger().critical("Could not load plugin", e); return null; } + }else{ + Plugin plugin = loader.simpleLoadPlugin(file); + this.plugins.put(plugin.getDescription().getName(),plugin); + List pluginCommands = this.parseSimplePluginCommands(plugin); + if (!pluginCommands.isEmpty()) { + this.commandMap.registerAll(plugin.getDescription().getName(), pluginCommands); + } + return plugin; } } } @@ -116,6 +127,7 @@ public Plugin loadPlugin(File file, Map loaders) { return null; } + public Map loadPlugins(String dictionary) { return this.loadPlugins(new File(dictionary)); } @@ -150,14 +162,15 @@ public Map loadPlugins(File dictionary, List newLoaders, } for (final PluginLoader loader : loaders.values()) { - for (File file : dictionary.listFiles((dir, name) -> { + File[] files = dictionary.listFiles((dir, name) -> { for (Pattern pattern : loader.getPluginFilters()) { if (pattern.matcher(name).matches()) { return true; } } return false; - })) { + }); + for (File file : files!=null?files:new File[0]) { if (file.isDirectory() && !includeDir) { continue; } @@ -267,14 +280,8 @@ public Map loadPlugins(File dictionary, List newLoaders, } if (!dependencies.containsKey(name) && !softDependencies.containsKey(name)) { - plugins.remove(name); missingDependency = false; - Plugin plugin = this.loadPlugin(file, loaders); - if (plugin != null) { - loadedPlugins.put(name, plugin); - } else { - this.server.getLogger().critical(this.server.getLanguage().translateString("nukkit.plugin.genericLoadError", name)); - } + load(plugins,name,file,loaders,loadedPlugins); } } @@ -283,14 +290,8 @@ public Map loadPlugins(File dictionary, List newLoaders, File file = plugins.get(name); if (!dependencies.containsKey(name)) { softDependencies.remove(name); - plugins.remove(name); missingDependency = false; - Plugin plugin = this.loadPlugin(file, loaders); - if (plugin != null) { - loadedPlugins.put(name, plugin); - } else { - this.server.getLogger().critical(this.server.getLanguage().translateString("nukkit.plugin.genericLoadError", name)); - } + load(plugins,name,file,loaders,loadedPlugins); } } @@ -309,6 +310,17 @@ public Map loadPlugins(File dictionary, List newLoaders, } } + + private void load(Map plugins,String name,File file,Map loaders,Map loadedPlugins){ + plugins.remove(name); + Plugin plugin = this.loadPlugin(file, loaders); + if (plugin != null) { + loadedPlugins.put(name, plugin); + } else { + this.server.getLogger().critical(this.server.getLanguage().translateString("nukkit.plugin.genericLoadError", name)); + } + } + public Permission getPermission(String name) { if (this.permissions.containsKey(name)) { return this.permissions.get(name); @@ -447,10 +459,51 @@ public void enablePlugin(Plugin plugin) { } } + protected List parseSimplePluginCommands(Plugin plugin){ + List pluginCmds = new ArrayList<>(); + Set> commands = plugin.getDescription().getCommands().entrySet(); + for(Map.Entry obj : commands){ + if(obj.getValue() instanceof Command) { + Command command = (Command) (obj.getValue()); + PluginCommand newCmd = new PluginCommand<>(command.name(), plugin); + initCommand(newCmd, command); + pluginCmds.add(newCmd); + } + } + Class pluginClass = plugin.getClass(); + Method[] methods = pluginClass.getDeclaredMethods(); + for(Method method:methods){ + Command cmd = method.getAnnotation(Command.class); + cn.nukkit.plugin.simple.Permission permission = + method.getAnnotation(cn.nukkit.plugin.simple.Permission.class); + if(cmd!=null&&permission!=null){ + plugin.getDescription().getPermissions().addAll(Permission.loadPermissions(Permission.parsePermission(new cn.nukkit.plugin.simple.Permission[] { + permission + }))); + SimplePluginCommand command = new SimplePluginCommand(cmd.name(),plugin); + initCommand(command,cmd); + command.setCommandMethod(method); + pluginCmds.add(command); + } + } + return pluginCmds; + } + + private void initCommand(PluginCommand newCmd,Command command){ + newCmd.setDescription(command.description()); + newCmd.setUsage(command.usage()); + newCmd.setAliases(command.aliases()); + newCmd.setPermission(command.permission()); + newCmd.setPermissionMessage(command.permissionMessage()); + } + protected List parseYamlCommands(Plugin plugin) { List pluginCmds = new ArrayList<>(); for (Map.Entry entry : plugin.getDescription().getCommands().entrySet()) { + if(entry.getValue() instanceof Command){ + continue; + } String key = (String) entry.getKey(); Object data = entry.getValue(); if (key.contains(":")) { diff --git a/src/main/java/cn/nukkit/plugin/simple/AutoPlugin.java b/src/main/java/cn/nukkit/plugin/simple/AutoPlugin.java new file mode 100644 index 00000000000..6d8487c4d12 --- /dev/null +++ b/src/main/java/cn/nukkit/plugin/simple/AutoPlugin.java @@ -0,0 +1,30 @@ +package cn.nukkit.plugin.simple; + + + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * You can use the AutoPlugin annotation to inject objects of the main class, + * which was recently added based on a simple plugin system. + * + * @ AutoPlugin + * private Plugin plugin; + * @ Override + * public boolean execute(CommandSender commandSender, String label, String[] strings) { + * plugin.getLogger().info("233");//no npe + * return true; + * } + * + * @author magiclu # DreamServer + * @see java.lang.annotation.Annotation + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.FIELD}) +public @interface AutoPlugin { + + +} diff --git a/src/main/java/cn/nukkit/plugin/simple/Children.java b/src/main/java/cn/nukkit/plugin/simple/Children.java new file mode 100644 index 00000000000..10d8e441127 --- /dev/null +++ b/src/main/java/cn/nukkit/plugin/simple/Children.java @@ -0,0 +1,16 @@ +package cn.nukkit.plugin.simple; + +import cn.nukkit.permission.Permission; + +/** + * The children permission + * @author magiclu # DreamServer + */ +public @interface Children { + + String name(); + + String description() default ""; + + String theDefault() default Permission.DEFAULT_PERMISSION; +} diff --git a/src/main/java/cn/nukkit/plugin/simple/Command.java b/src/main/java/cn/nukkit/plugin/simple/Command.java new file mode 100644 index 00000000000..c31b4b4a123 --- /dev/null +++ b/src/main/java/cn/nukkit/plugin/simple/Command.java @@ -0,0 +1,27 @@ +package cn.nukkit.plugin.simple; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Command auto-registration for launching SimplePlugin + * @author magiclu # DreamServer + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE,ElementType.METHOD}) +public @interface Command { + + String name(); + + String usage() default ""; + + String description() default ""; + + String permission(); + + String[] aliases() default {}; + + String permissionMessage() default ""; +} diff --git a/src/main/java/cn/nukkit/plugin/simple/EnableCommand.java b/src/main/java/cn/nukkit/plugin/simple/EnableCommand.java new file mode 100644 index 00000000000..56b5e5cb551 --- /dev/null +++ b/src/main/java/cn/nukkit/plugin/simple/EnableCommand.java @@ -0,0 +1,18 @@ +package cn.nukkit.plugin.simple; + +import cn.nukkit.command.Command; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author magiclu # DreamServer + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE}) +public @interface EnableCommand { + + Class[] noRegister() default {}; +} diff --git a/src/main/java/cn/nukkit/plugin/simple/EnableRegister.java b/src/main/java/cn/nukkit/plugin/simple/EnableRegister.java new file mode 100644 index 00000000000..b766c95aa65 --- /dev/null +++ b/src/main/java/cn/nukkit/plugin/simple/EnableRegister.java @@ -0,0 +1,19 @@ +package cn.nukkit.plugin.simple; + +import cn.nukkit.event.Listener; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Listener auto-registration for launching SimplePlugin + * @author magiclu # DreamServer + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE}) +public @interface EnableRegister { + + Class[] noRegister() default {}; +} diff --git a/src/main/java/cn/nukkit/plugin/simple/Main.java b/src/main/java/cn/nukkit/plugin/simple/Main.java new file mode 100644 index 00000000000..d44e96b08e3 --- /dev/null +++ b/src/main/java/cn/nukkit/plugin/simple/Main.java @@ -0,0 +1,50 @@ +package cn.nukkit.plugin.simple; + +import cn.nukkit.plugin.PluginLoadOrder; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * main class positioning annotation. With this annotation, + * you can locate the main class and load configuration parameters + * without writing plugin.yml. + * + * @ Main(name="hello",api="1.0.9") + * @author magiclu # DreamServer + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface Main { + + + String name(); + + String version() default "0.0.1"; + + String author() default ""; + + String[] api(); + + String[] depend() default {}; + + String[] loadBefore() default {}; + + String [] softDepend() default {}; + + String description() default ""; + + PluginLoadOrder load() default PluginLoadOrder.POSTWORLD; + + String website() default ""; + + String prefix() default ""; + + Command[] commands() default {}; + + Permission[] permissions() default {}; + + +} diff --git a/src/main/java/cn/nukkit/plugin/simple/Permission.java b/src/main/java/cn/nukkit/plugin/simple/Permission.java new file mode 100644 index 00000000000..22e12ba897c --- /dev/null +++ b/src/main/java/cn/nukkit/plugin/simple/Permission.java @@ -0,0 +1,23 @@ +package cn.nukkit.plugin.simple; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * used with Command. + * @author magiclu # DreamServer + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE,ElementType.METHOD}) +public @interface Permission { + + String permission(); + + String description() default ""; + + String theDefault() default cn.nukkit.permission.Permission.DEFAULT_PERMISSION; + + Children[] childeren() default {}; +} diff --git a/src/main/java/cn/nukkit/plugin/simple/SimpleCommandData.java b/src/main/java/cn/nukkit/plugin/simple/SimpleCommandData.java new file mode 100644 index 00000000000..eb4f189849e --- /dev/null +++ b/src/main/java/cn/nukkit/plugin/simple/SimpleCommandData.java @@ -0,0 +1,38 @@ +package cn.nukkit.plugin.simple; + +import cn.nukkit.command.Command; +import cn.nukkit.command.CommandSender; + +public class SimpleCommandData { + + public SimpleCommandData(CommandSender sender, Command command, String label, String[] args) { + this.sender = sender; + this.command = command; + this.label = label; + this.args = args; + } + + private CommandSender sender; + + private cn.nukkit.command.Command command; + + private String label; + + private String[] args; + + public Command getCommand() { + return command; + } + + public CommandSender getSender() { + return sender; + } + + public String getLabel() { + return label; + } + + public String[] getArgs() { + return args; + } +} diff --git a/src/main/java/cn/nukkit/plugin/simple/SimplePluginCommand.java b/src/main/java/cn/nukkit/plugin/simple/SimplePluginCommand.java new file mode 100644 index 00000000000..dbc689071b1 --- /dev/null +++ b/src/main/java/cn/nukkit/plugin/simple/SimplePluginCommand.java @@ -0,0 +1,55 @@ +package cn.nukkit.plugin.simple; + +import cn.nukkit.command.CommandSender; +import cn.nukkit.command.PluginCommand; +import cn.nukkit.lang.TranslationContainer; +import cn.nukkit.plugin.Plugin; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +public class SimplePluginCommand extends PluginCommand { + + private Method commandMethod; + + public SimplePluginCommand(String name, Plugin owner) { + super(name, owner); + } + + public void setCommandMethod(Method commandMethod) { + this.commandMethod = commandMethod; + } + + + @Override + public boolean execute(CommandSender sender, String commandLabel, String[] args) { + try { + if (!this.owningPlugin.isEnabled()) { + return false; + } + + if (!this.testPermission(sender)) { + return false; + } + boolean success = false; + Class[] clzs = commandMethod.getParameterTypes(); + if(clzs.length!=0){ + if(clzs[0].equals(SimpleCommandData.class)){ + success = (Boolean) commandMethod.invoke(owningPlugin,new SimpleCommandData(sender,this,commandLabel,args)); + }else{ + success = (Boolean) commandMethod.invoke(owningPlugin, sender, this, commandLabel, args); + } + } + + + if (!success && !this.usageMessage.equals("")) { + sender.sendMessage(new TranslationContainer("commands.generic.usage", this.usageMessage)); + } + + return success; + }catch (IllegalAccessException| InvocationTargetException e){ + e.printStackTrace(); + } + return false; + } +} diff --git a/src/test/java/cn/nukkit/test/PluginTest.java b/src/test/java/cn/nukkit/test/PluginTest.java new file mode 100644 index 00000000000..6a51e0aa900 --- /dev/null +++ b/src/test/java/cn/nukkit/test/PluginTest.java @@ -0,0 +1,20 @@ +package cn.nukkit.test; + +import cn.nukkit.plugin.PluginBase; +import cn.nukkit.plugin.simple.Command; +import cn.nukkit.plugin.simple.Main; +import cn.nukkit.plugin.simple.Permission; + +@Main(name="hello",api="1.0.9",commands = { + @Command( + name="hello", + permission = "hello.test" + ) +},permissions = { + @Permission( + permission = "hello.test", + theDefault = "op" + ) +}) +public class PluginTest extends PluginBase { +}