summaryrefslogtreecommitdiffstats
path: root/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'src/main')
-rw-r--r--src/main/java/org/bukkit/plugin/java/annotation/Commands.java52
-rw-r--r--src/main/java/org/bukkit/plugin/java/annotation/DependsOn.java17
-rw-r--r--src/main/java/org/bukkit/plugin/java/annotation/LoadBefore.java17
-rw-r--r--src/main/java/org/bukkit/plugin/java/annotation/Permissions.java50
-rw-r--r--src/main/java/org/bukkit/plugin/java/annotation/PluginAnnotationProcessor.java223
-rw-r--r--src/main/java/org/bukkit/plugin/java/annotation/SoftDependsOn.java17
-rw-r--r--src/main/java/org/bukkit/plugin/java/annotation/UsesDatabase.java13
-rw-r--r--src/main/java/org/bukkit/plugin/java/annotation/Website.java17
-rw-r--r--src/main/java/org/bukkit/plugin/java/annotation/command/Command.java48
-rw-r--r--src/main/java/org/bukkit/plugin/java/annotation/command/Commands.java20
-rw-r--r--src/main/java/org/bukkit/plugin/java/annotation/dependency/Dependency.java19
-rw-r--r--src/main/java/org/bukkit/plugin/java/annotation/dependency/DependsOn.java20
-rw-r--r--src/main/java/org/bukkit/plugin/java/annotation/dependency/LoadBefore.java21
-rw-r--r--src/main/java/org/bukkit/plugin/java/annotation/dependency/LoadBeforePlugins.java17
-rw-r--r--src/main/java/org/bukkit/plugin/java/annotation/dependency/SoftDependency.java22
-rw-r--r--src/main/java/org/bukkit/plugin/java/annotation/dependency/SoftDependsOn.java23
-rw-r--r--src/main/java/org/bukkit/plugin/java/annotation/permission/ChildPermission.java18
-rw-r--r--src/main/java/org/bukkit/plugin/java/annotation/permission/Permission.java40
-rw-r--r--src/main/java/org/bukkit/plugin/java/annotation/permission/Permissions.java20
-rw-r--r--src/main/java/org/bukkit/plugin/java/annotation/plugin/Description.java (renamed from src/main/java/org/bukkit/plugin/java/annotation/Description.java)10
-rw-r--r--src/main/java/org/bukkit/plugin/java/annotation/plugin/LoadOn.java (renamed from src/main/java/org/bukkit/plugin/java/annotation/LoadOn.java)10
-rw-r--r--src/main/java/org/bukkit/plugin/java/annotation/plugin/LogPrefix.java (renamed from src/main/java/org/bukkit/plugin/java/annotation/LogPrefix.java)10
-rw-r--r--src/main/java/org/bukkit/plugin/java/annotation/plugin/Main.java (renamed from src/main/java/org/bukkit/plugin/java/annotation/Main.java)27
-rw-r--r--src/main/java/org/bukkit/plugin/java/annotation/plugin/Name.java (renamed from src/main/java/org/bukkit/plugin/java/annotation/Name.java)13
-rw-r--r--src/main/java/org/bukkit/plugin/java/annotation/plugin/Plugin.java24
-rw-r--r--src/main/java/org/bukkit/plugin/java/annotation/plugin/UsesDatabase.java20
-rw-r--r--src/main/java/org/bukkit/plugin/java/annotation/plugin/Version.java (renamed from src/main/java/org/bukkit/plugin/java/annotation/Version.java)14
-rw-r--r--src/main/java/org/bukkit/plugin/java/annotation/plugin/Website.java20
-rw-r--r--src/main/java/org/bukkit/plugin/java/annotation/plugin/author/Author.java (renamed from src/main/java/org/bukkit/plugin/java/annotation/Author.java)14
-rw-r--r--src/main/java/org/bukkit/plugin/java/annotation/plugin/author/Authors.java14
30 files changed, 557 insertions, 293 deletions
diff --git a/src/main/java/org/bukkit/plugin/java/annotation/Commands.java b/src/main/java/org/bukkit/plugin/java/annotation/Commands.java
deleted file mode 100644
index c730b59..0000000
--- a/src/main/java/org/bukkit/plugin/java/annotation/Commands.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package org.bukkit.plugin.java.annotation;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Target;
-
-/**
- * Part of the plugin annotations framework.
- * <p>
- * Represents a list of this plugin's registered commands.
- */
-
-@Target(ElementType.TYPE)
-public @interface Commands { // TODO: in java 8, make repeatable.
-
- public Cmd[] value();
-
- @Target({})
- public static @interface Cmd {
-
- /**
- * This command's name.
- */
- public String value();
-
- /**
- * This command's description.
- */
-
- public String desc() default "";
-
- /**
- * This command's aliases.
- */
- public String[] aliases() default {};
-
- /**
- * This command's permission node.
- */
- public String permission() default "";
-
- /**
- * This command's permission-check-fail message.
- */
- public String permissionMessage() default "";
-
- /**
- * This command's usage message.
- */
- public String usage() default "";
- }
-
-}
diff --git a/src/main/java/org/bukkit/plugin/java/annotation/DependsOn.java b/src/main/java/org/bukkit/plugin/java/annotation/DependsOn.java
deleted file mode 100644
index 892a267..0000000
--- a/src/main/java/org/bukkit/plugin/java/annotation/DependsOn.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package org.bukkit.plugin.java.annotation;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Target;
-
-/**
- * Part of the plugin annotations framework.
- * <p>
- * Represents the plugin's hard dependencies.
- */
-
-@Target(ElementType.TYPE)
-public @interface DependsOn {
-
- public String[] value();
-
-}
diff --git a/src/main/java/org/bukkit/plugin/java/annotation/LoadBefore.java b/src/main/java/org/bukkit/plugin/java/annotation/LoadBefore.java
deleted file mode 100644
index d0802f4..0000000
--- a/src/main/java/org/bukkit/plugin/java/annotation/LoadBefore.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package org.bukkit.plugin.java.annotation;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Target;
-
-/**
- * Part of the plugin annotations framework.
- * <p>
- * Represents the plugins this plugin should be loaded before
- */
-
-@Target(ElementType.TYPE)
-public @interface LoadBefore {
-
- public String[] value();
-
-}
diff --git a/src/main/java/org/bukkit/plugin/java/annotation/Permissions.java b/src/main/java/org/bukkit/plugin/java/annotation/Permissions.java
deleted file mode 100644
index c6097c3..0000000
--- a/src/main/java/org/bukkit/plugin/java/annotation/Permissions.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package org.bukkit.plugin.java.annotation;
-
-import org.bukkit.permissions.PermissionDefault;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Target;
-
-/**
- * Part of the plugin annotations framework.
- * <p>
- * Represents a list of this plugin's registered permissions.
- */
-
-@Target(ElementType.TYPE)
-public @interface Permissions { // TODO: in java 8, make repeatable.
-
- public Perm[] value();
-
- @Target({})
- public static @interface Perm {
-
- /**
- * This perm's name.
- */
- public String value();
-
- /**
- * This perm's description.
- */
-
- public String desc() default "";
-
- /**
- * This perm's default.
- */
- public PermissionDefault defaultValue() default PermissionDefault.OP;
-
- /**
- * This perm's child nodes
- */
- public String[] children() default {};
-
- /**
- * This perms's negated child nodes
- */
- public String[] antichildren() default {};
-
- }
-
-}
diff --git a/src/main/java/org/bukkit/plugin/java/annotation/PluginAnnotationProcessor.java b/src/main/java/org/bukkit/plugin/java/annotation/PluginAnnotationProcessor.java
index 9266c97..9557b79 100644
--- a/src/main/java/org/bukkit/plugin/java/annotation/PluginAnnotationProcessor.java
+++ b/src/main/java/org/bukkit/plugin/java/annotation/PluginAnnotationProcessor.java
@@ -1,163 +1,220 @@
package org.bukkit.plugin.java.annotation;
-import org.bukkit.plugin.PluginLoadOrder;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
import org.bukkit.plugin.java.JavaPlugin;
+import org.bukkit.plugin.java.annotation.command.Command;
+import org.bukkit.plugin.java.annotation.dependency.Dependency;
+import org.bukkit.plugin.java.annotation.dependency.LoadBefore;
+import org.bukkit.plugin.java.annotation.dependency.SoftDependency;
+import org.bukkit.plugin.java.annotation.permission.ChildPermission;
+import org.bukkit.plugin.java.annotation.permission.Permission;
+import org.bukkit.plugin.java.annotation.plugin.Description;
+import org.bukkit.plugin.java.annotation.plugin.LoadOn;
+import org.bukkit.plugin.java.annotation.plugin.LogPrefix;
+import org.bukkit.plugin.java.annotation.plugin.Plugin;
+import org.bukkit.plugin.java.annotation.plugin.UsesDatabase;
+import org.bukkit.plugin.java.annotation.plugin.Website;
+import org.bukkit.plugin.java.annotation.plugin.author.Author;
+import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.Yaml;
+import org.yaml.snakeyaml.nodes.Tag;
-import javax.annotation.processing.*;
+
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.RoundEnvironment;
+import javax.annotation.processing.SupportedAnnotationTypes;
+import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.TypeMirror;
+import javax.swing.text.DateFormatter;
import javax.tools.Diagnostic;
import javax.tools.FileObject;
import javax.tools.StandardLocation;
import java.io.IOException;
-import java.io.StringWriter;
+import java.io.InputStream;
import java.io.Writer;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
import java.util.Date;
-import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.Set;
@SupportedAnnotationTypes("org.bukkit.plugin.java.annotation.*")
-@SupportedSourceVersion(SourceVersion.RELEASE_6)
+@SupportedSourceVersion(SourceVersion.RELEASE_8)
public class PluginAnnotationProcessor extends AbstractProcessor {
private boolean hasMainBeenFound = false;
- private static final DateFormat dFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
+ private static final DateTimeFormatter dFormat = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss", Locale.ENGLISH);
@Override
public boolean process(Set<? extends TypeElement> annots, RoundEnvironment rEnv) {
Element main = null;
- for(Element el : rEnv.getElementsAnnotatedWith(Main.class)) {
- if(main != null){
- raiseError("More than one class with @Main found, aborting!");
- return false;
- }
- main = el;
- }
+ hasMainBeenFound = false;
- if(main == null) return false;
+ Set<? extends Element> elements = rEnv.getElementsAnnotatedWith(Plugin.class);
+ if(elements.size() > 1) {
+ raiseError("Found more than one plugin main class");
+ return false;
+ }
+ if(elements.isEmpty()) {
+ return false;
+ }
if(hasMainBeenFound){
- raiseError("More than one class with @Main found, aborting!");
+ raiseError("The plugin class has already been located, aborting!");
return false;
}
+ main = elements.iterator().next();
hasMainBeenFound = true;
TypeElement mainType;
if(main instanceof TypeElement){
mainType = (TypeElement) main;
} else {
- raiseError("Element annotated with @Main is not a type!");
+ raiseError("Element annotated with @Main is not a type!", main);
return false;
}
if(!(mainType.getEnclosingElement() instanceof PackageElement) && !mainType.getModifiers().contains(Modifier.STATIC)){
- raiseError("Element annotated with @Main is not top-level or static nested!");
+ raiseError("Element annotated with @Main is not top-level or static nested!", mainType);
return false;
}
if(!processingEnv.getTypeUtils().isSubtype(mainType.asType(), fromClass(JavaPlugin.class))){
- raiseError("Class annotated with @Main is not an subclass of JavaPlugin!");
+ raiseError("Class annotated with @Main is not an subclass of JavaPlugin!", mainType);
}
- Map<String, Object> yml = new HashMap<String, Object>();
+ Map<String, Object> yml = Maps.newLinkedHashMap(); // linked so we can maintain the same output into file for sanity
+ // populate mainName
final String mainName = mainType.getQualifiedName().toString();
- yml.put("main", mainName);
+ yml.put("main", mainName); // always override this so we make sure the main class name is correct
- processAndPut(yml, "name", mainType, mainName.substring(mainName.lastIndexOf('.') + 1), Name.class, String.class);
+ // populate plugin name
+ processAndPut(yml, "name", mainType, mainName.substring(mainName.lastIndexOf('.') + 1), Plugin.class, String.class, "name");
- processAndPut(yml, "version", mainType, Version.DEFAULT_VERSION, Version.class, String.class);
+ // populate version
+ processAndPut(yml, "version", mainType, Plugin.DEFAULT_VERSION, Plugin.class, String.class, "version");
- processAndPut(yml, "description", mainType, null, Description.class, String.class);
+ // populate plugin description
+ processAndPut(yml, "description", mainType, null, Description.class, String.class, "desc");
- processAndPut(yml, "load", mainType, null, LoadOn.class, String.class);
+ // populate plugin load order
+ processAndPut(yml, "load", mainType, null, LoadOn.class, String.class,"loadOn");
- {
- String[] authors = process(mainType, new String[0], Author.class, String[].class);
- switch(authors.length) {
- case 0: break;
- case 1: yml.put("author", authors[0]); break;
- default: yml.put("authors", authors); break;
- }
+ // authors
+ Author[] authors = mainType.getAnnotationsByType(Author.class);
+ List<String> authorMap = Lists.newArrayList();
+ for(Author auth : authors) {
+ authorMap.add(auth.name());
+ }
+ if(authorMap.size() > 1) {
+ yml.put("authors", authorMap);
+ } else if(authorMap.size() == 1) {
+ yml.put("author", authorMap.iterator().next());
}
- processAndPut(yml, "website", mainType, null, Website.class, String.class);
-
- if(mainType.getAnnotation(UsesDatabase.class) != null) yml.put("database", true);
-
- processAndPut(yml, "depend", mainType, null, DependsOn.class, String[].class);
-
- processAndPut(yml, "softdepend", mainType, null, SoftDependsOn.class, String[].class);
-
- processAndPut(yml, "prefix", mainType, null, LogPrefix.class, String.class);
+ // website
+ processAndPut(yml, "website", mainType, null, Website.class, String.class, "url");
- processAndPut(yml, "loadbefore", mainType, null, LoadBefore.class, String[].class);
+ // prefix
+ processAndPut(yml, "prefix", mainType, null, LogPrefix.class, String.class, "prefix");
- Commands.Cmd[] commands = process(mainType, new Commands.Cmd[0], Commands.class, Commands.Cmd[].class);
+ // dependencies
+ Dependency[] dependencies = mainType.getAnnotationsByType(Dependency.class);
+ List<String> hardDependencies = Lists.newArrayList();
+ for(Dependency dep : dependencies) {
+ hardDependencies.add(dep.plugin());
+ }
+ if(!hardDependencies.isEmpty()) yml.putIfAbsent("depend", hardDependencies);
- Map<String, Object> commandMap = new HashMap<String, Object>();
+ // soft-dependencies
+ SoftDependency[] softDependencies = mainType.getAnnotationsByType(SoftDependency.class);
+ String[] softDepArr = new String[softDependencies.length];
+ for(int i = 0; i < softDependencies.length; i++) {
+ softDepArr[i] = softDependencies[i].plugin();
+ }
+ if(softDepArr.length > 0) yml.putIfAbsent("softdepend", softDepArr);
- for(Commands.Cmd cmd : commands) {
- String name = cmd.value();
- Map<String, Object> desc = new HashMap<String, Object>();
- if(!cmd.desc().isEmpty()) desc.put("description", cmd.desc());
- if(cmd.aliases().length != 0) desc.put("aliases", cmd.aliases());
- if(!cmd.permission().isEmpty()) desc.put("permission", cmd.permission());
- if(!cmd.permissionMessage().isEmpty()) desc.put("permission-message", cmd.permissionMessage());
- if(!cmd.usage().isEmpty()) desc.put("usage", cmd.usage());
+ // load-before
+ LoadBefore[] loadBefore = mainType.getAnnotationsByType(LoadBefore.class);
+ String[] loadBeforeArr = new String[loadBefore.length];
+ for(int i = 0; i < loadBefore.length; i++) {
+ loadBeforeArr[i] = loadBefore[i].plugin();
+ }
+ if(loadBeforeArr.length > 0) yml.putIfAbsent("loadbefore", loadBeforeArr);
+
+ // commands
+ Command[] commands = mainType.getAnnotationsByType(Command.class);
+ Map<String, Object> commandMap = Maps.newLinkedHashMap();
+ for(Command command : commands) {
+ Map<String, Object> desc = Maps.newLinkedHashMap();
+ String name = command.name();
+ if(!command.desc().isEmpty()) desc.put("description", command.desc());
+ if(command.aliases().length != 0) desc.put("aliases", command.aliases());
+ if(!command.permission().isEmpty()) desc.put("permission", command.permission());
+ if(!command.permissionMessage().isEmpty()) desc.put("permission-message", command.permissionMessage());
+ if(!command.usage().isEmpty()) desc.put("usage", command.usage());
commandMap.put(name, desc);
}
-
- if(!commandMap.isEmpty()) yml.put("commands", commandMap);
-
- Permissions.Perm[] perms = process(mainType, new Permissions.Perm[0], Permissions.class, Permissions.Perm[].class);
-
- Map<String, Object> permMap = new HashMap<String, Object>();
-
- for(Permissions.Perm perm : perms) {
- String name = perm.value();
- Map<String, Object> desc = new HashMap<String, Object>();
+ if(!commandMap.isEmpty()) yml.putIfAbsent("commands", commandMap);
+
+ // permissions
+ Permission[] permissions = mainType.getAnnotationsByType(Permission.class);
+ Map<String, Object> permMap = Maps.newLinkedHashMap();
+ for(Permission perm : permissions) {
+ Map<String, Object> desc = Maps.newLinkedHashMap();
+ String name = perm.name();
if(!perm.desc().isEmpty()) desc.put("description", perm.desc());
desc.put("default", perm.defaultValue().toString());
- Map<String, Object> children = new HashMap<String, Object>();
- for(String p : perm.children()) children.put(p, true);
- for(String p : perm.antichildren()) children.put(p, false);
+ Map<String, Object> children = Maps.newLinkedHashMap();
+ for(ChildPermission child : perm.children()) {
+ children.put(child.name(), child.inherit());
+ }
if(!children.isEmpty()) desc.put("children", children);
permMap.put(name, desc);
}
+ if(!permMap.isEmpty()) yml.putIfAbsent("permissions", permMap);
- if(!permMap.isEmpty()) yml.put("permissions", permMap);
+ // database D: //TODO: Remove me!
+ if(mainType.getAnnotation(UsesDatabase.class) != null) {
+ yml.put("database", true);
+ processingEnv.getMessager().printMessage(Diagnostic.Kind.MANDATORY_WARNING, "Database support was dropped in Bukkit in version 1.12.", mainType);
+ }
Yaml yaml = new Yaml();
-
try {
FileObject file = this.processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", "plugin.yml");
- Writer w = file.openWriter();
- try{
- w.append("# Auto-generated plugin.yml, generated at ").append(dFormat.format(new Date())).append(" by ").append(this.getClass().getName()).append("\n\n");
- yaml.dump(yml, w);
- } finally {
+ try(Writer w = file.openWriter()) {
+ w.append("# Auto-generated plugin.yml, generated at ")
+ .append(LocalDateTime.now().format(dFormat))
+ .append(" by ")
+ .append(this.getClass().getName())
+ .append("\n\n");
+ // have to format the yaml explicitly because otherwise it dumps child nodes as maps within braces.
+ String raw = yaml.dumpAs(yml, Tag.MAP, DumperOptions.FlowStyle.BLOCK);
+ w.write(raw);
w.flush();
w.close();
}
-
+ // try with resources will close the Writer since it implements Closeable
} catch (IOException e) {
throw new RuntimeException(e);
}
processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING, "NOTE: You are using org.bukkit.plugin.java.annotation, an experimental API!");
-
return true;
}
@@ -165,28 +222,38 @@ public class PluginAnnotationProcessor extends AbstractProcessor {
this.processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, message);
}
+ private void raiseError(String message, Element element) {
+ this.processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, message, element);
+ }
+
private TypeMirror fromClass(Class<?> clazz) {
return processingEnv.getElementUtils().getTypeElement(clazz.getName()).asType();
}
private <A extends Annotation, R> R processAndPut(
Map<String, Object> map, String name, Element el, R defaultVal, Class<A> annotationType, Class<R> returnType) {
- R result = process(el, defaultVal, annotationType, returnType);
+ return processAndPut(map, name, el, defaultVal, annotationType, returnType, "value");
+ }
+
+ private <A extends Annotation, R> R processAndPut(
+ Map<String, Object> map, String name, Element el, R defaultVal, Class<A> annotationType, Class<R> returnType, String methodName) {
+ R result = process(el, defaultVal, annotationType, returnType, methodName);
if(result != null)
- map.put(name, result);
+ map.putIfAbsent(name, result);
return result;
}
- private <A extends Annotation, R> R process(Element el, R defaultVal, Class<A> annotationType, Class<R> returnType) {
+
+ private <A extends Annotation, R> R process(Element el, R defaultVal, Class<A> annotationType, Class<R> returnType, String methodName) {
R result;
A ann = el.getAnnotation(annotationType);
if(ann == null) result = defaultVal;
else {
try {
- Method value = annotationType.getMethod("value");
+ Method value = annotationType.getMethod(methodName);
Object res = value.invoke(ann);
result = (R) (returnType == String.class ? res.toString() : returnType.cast(res));
} catch (Exception e) {
- throw new RuntimeException(e); // shouldn't happen in theory
+ throw new RuntimeException(e); // shouldn't happen in theory (blame Choco if it does)
}
}
return result;
diff --git a/src/main/java/org/bukkit/plugin/java/annotation/SoftDependsOn.java b/src/main/java/org/bukkit/plugin/java/annotation/SoftDependsOn.java
deleted file mode 100644
index 81e8662..0000000
--- a/src/main/java/org/bukkit/plugin/java/annotation/SoftDependsOn.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package org.bukkit.plugin.java.annotation;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Target;
-
-/**
- * Part of the plugin annotations framework.
- * <p>
- * Represents the plugin's soft dependencies.
- */
-
-@Target(ElementType.TYPE)
-public @interface SoftDependsOn {
-
- public String[] value();
-
-}
diff --git a/src/main/java/org/bukkit/plugin/java/annotation/UsesDatabase.java b/src/main/java/org/bukkit/plugin/java/annotation/UsesDatabase.java
deleted file mode 100644
index e73ebfc..0000000
--- a/src/main/java/org/bukkit/plugin/java/annotation/UsesDatabase.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package org.bukkit.plugin.java.annotation;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Target;
-
-/**
- * Part of the plugin annotations framework.
- * <p>
- * Denotes this plugin as using Bukkit's bundled database system.
- */
-
-@Target(ElementType.TYPE)
-public @interface UsesDatabase {}
diff --git a/src/main/java/org/bukkit/plugin/java/annotation/Website.java b/src/main/java/org/bukkit/plugin/java/annotation/Website.java
deleted file mode 100644
index 385483f..0000000
--- a/src/main/java/org/bukkit/plugin/java/annotation/Website.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package org.bukkit.plugin.java.annotation;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Target;
-
-/**
- * Part of the plugin annotations framework.
- * <p>
- * Represents the website of the plugin.
- */
-
-@Target(ElementType.TYPE)
-public @interface Website {
-
- public String value();
-
-} \ No newline at end of file
diff --git a/src/main/java/org/bukkit/plugin/java/annotation/command/Command.java b/src/main/java/org/bukkit/plugin/java/annotation/command/Command.java
new file mode 100644
index 0000000..9d54dee
--- /dev/null
+++ b/src/main/java/org/bukkit/plugin/java/annotation/command/Command.java
@@ -0,0 +1,48 @@
+package org.bukkit.plugin.java.annotation.command;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Repeatable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Defines a plugin command
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+@Repeatable(Commands.class)
+public @interface Command {
+
+ /**
+ * This command's name.
+ */
+ String name();
+
+ /**
+ * This command's description.
+ */
+ String desc() default "";
+
+ /**
+ * This command's aliases.
+ */
+ String[] aliases() default {};
+
+ /**
+ * This command's permission node.
+ */
+ String permission() default "";
+
+ /**
+ * This command's permission-check-fail message.
+ */
+ String permissionMessage() default "";
+
+ /**
+ * This command's usage message.
+ */
+ String usage() default "";
+}
diff --git a/src/main/java/org/bukkit/plugin/java/annotation/command/Commands.java b/src/main/java/org/bukkit/plugin/java/annotation/command/Commands.java
new file mode 100644
index 0000000..c98a77b
--- /dev/null
+++ b/src/main/java/org/bukkit/plugin/java/annotation/command/Commands.java
@@ -0,0 +1,20 @@
+package org.bukkit.plugin.java.annotation.command;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Part of the plugin annotations framework.
+ * <p>
+ * Represents a list of this plugin's registered command(s).
+ */
+
+@Documented
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Commands {
+ Command[] value() default {};
+}
diff --git a/src/main/java/org/bukkit/plugin/java/annotation/dependency/Dependency.java b/src/main/java/org/bukkit/plugin/java/annotation/dependency/Dependency.java
new file mode 100644
index 0000000..42872f0
--- /dev/null
+++ b/src/main/java/org/bukkit/plugin/java/annotation/dependency/Dependency.java
@@ -0,0 +1,19 @@
+package org.bukkit.plugin.java.annotation.dependency;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Repeatable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Defines a plugin dependency
+ */
+@Documented
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.SOURCE)
+@Repeatable(DependsOn.class)
+public @interface Dependency {
+ String plugin();
+}
diff --git a/src/main/java/org/bukkit/plugin/java/annotation/dependency/DependsOn.java b/src/main/java/org/bukkit/plugin/java/annotation/dependency/DependsOn.java
new file mode 100644
index 0000000..e94d612
--- /dev/null
+++ b/src/main/java/org/bukkit/plugin/java/annotation/dependency/DependsOn.java
@@ -0,0 +1,20 @@
+package org.bukkit.plugin.java.annotation.dependency;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Part of the plugin annotations framework.
+ * <p>
+ * Represents the plugins a plugin depends on in order to be loaded
+ */
+@Documented
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.SOURCE)
+public @interface DependsOn {
+ Dependency[] value() default {};
+
+}
diff --git a/src/main/java/org/bukkit/plugin/java/annotation/dependency/LoadBefore.java b/src/main/java/org/bukkit/plugin/java/annotation/dependency/LoadBefore.java
new file mode 100644
index 0000000..25388ea
--- /dev/null
+++ b/src/main/java/org/bukkit/plugin/java/annotation/dependency/LoadBefore.java
@@ -0,0 +1,21 @@
+package org.bukkit.plugin.java.annotation.dependency;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Repeatable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Part of the plugin annotations framework.
+ * <p>
+ * Represents the plugin this plugin should be loaded before
+ */
+@Documented
+@Retention(RetentionPolicy.SOURCE)
+@Target(ElementType.TYPE)
+@Repeatable(LoadBeforePlugins.class)
+public @interface LoadBefore {
+ String plugin();
+}
diff --git a/src/main/java/org/bukkit/plugin/java/annotation/dependency/LoadBeforePlugins.java b/src/main/java/org/bukkit/plugin/java/annotation/dependency/LoadBeforePlugins.java
new file mode 100644
index 0000000..400d1d7
--- /dev/null
+++ b/src/main/java/org/bukkit/plugin/java/annotation/dependency/LoadBeforePlugins.java
@@ -0,0 +1,17 @@
+package org.bukkit.plugin.java.annotation.dependency;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Defines a list of plugin to load before this plugin
+ */
+@Documented
+@Retention(RetentionPolicy.SOURCE)
+@Target(ElementType.TYPE)
+public @interface LoadBeforePlugins {
+ LoadBefore[] value() default {};
+}
diff --git a/src/main/java/org/bukkit/plugin/java/annotation/dependency/SoftDependency.java b/src/main/java/org/bukkit/plugin/java/annotation/dependency/SoftDependency.java
new file mode 100644
index 0000000..cc36edc
--- /dev/null
+++ b/src/main/java/org/bukkit/plugin/java/annotation/dependency/SoftDependency.java
@@ -0,0 +1,22 @@
+package org.bukkit.plugin.java.annotation.dependency;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Repeatable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+
+/**
+ * Represents a soft (optional) dependency for this plugin.
+ * If this dependency is not present, the plugin will still load.
+ */
+
+@Documented
+@Retention(RetentionPolicy.SOURCE)
+@Target(ElementType.TYPE)
+@Repeatable(SoftDependsOn.class)
+public @interface SoftDependency {
+ String plugin();
+}
diff --git a/src/main/java/org/bukkit/plugin/java/annotation/dependency/SoftDependsOn.java b/src/main/java/org/bukkit/plugin/java/annotation/dependency/SoftDependsOn.java
new file mode 100644
index 0000000..6be9631
--- /dev/null
+++ b/src/main/java/org/bukkit/plugin/java/annotation/dependency/SoftDependsOn.java
@@ -0,0 +1,23 @@
+package org.bukkit.plugin.java.annotation.dependency;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Part of the plugin annotations framework.
+ * <p>
+ * Represents the plugins this plugin should try to load before this plugin will attempt to load.
+ * A plugin will still load if a soft dependency is not present.
+ */
+
+@Documented
+@Retention(RetentionPolicy.SOURCE)
+@Target(ElementType.TYPE)
+public @interface SoftDependsOn {
+
+ SoftDependency[] value() default {};
+
+}
diff --git a/src/main/java/org/bukkit/plugin/java/annotation/permission/ChildPermission.java b/src/main/java/org/bukkit/plugin/java/annotation/permission/ChildPermission.java
new file mode 100644
index 0000000..e22789e
--- /dev/null
+++ b/src/main/java/org/bukkit/plugin/java/annotation/permission/ChildPermission.java
@@ -0,0 +1,18 @@
+package org.bukkit.plugin.java.annotation.permission;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Defines a child permission for {@link Permission}
+ */
+@Documented
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.SOURCE)
+public @interface ChildPermission {
+ boolean inherit() default true;
+ String name();
+}
diff --git a/src/main/java/org/bukkit/plugin/java/annotation/permission/Permission.java b/src/main/java/org/bukkit/plugin/java/annotation/permission/Permission.java
new file mode 100644
index 0000000..35a72ab
--- /dev/null
+++ b/src/main/java/org/bukkit/plugin/java/annotation/permission/Permission.java
@@ -0,0 +1,40 @@
+package org.bukkit.plugin.java.annotation.permission;
+
+import org.bukkit.permissions.PermissionDefault;
+import org.bukkit.plugin.java.annotation.plugin.author.Authors;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Repeatable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Defines a plugin permission
+ */
+@Documented
+@Retention(RetentionPolicy.SOURCE)
+@Target(ElementType.TYPE)
+@Repeatable(Permissions.class)
+public @interface Permission {
+ /**
+ * This perm's name.
+ */
+ String name();
+
+ /**
+ * This perm's description.
+ */
+ String desc() default "";
+
+ /**
+ * This perm's default {@link PermissionDefault}
+ */
+ PermissionDefault defaultValue() default PermissionDefault.OP;
+
+ /**
+ * This permission's child nodes
+ */
+ ChildPermission[] children() default {};
+}
diff --git a/src/main/java/org/bukkit/plugin/java/annotation/permission/Permissions.java b/src/main/java/org/bukkit/plugin/java/annotation/permission/Permissions.java
new file mode 100644
index 0000000..9557769
--- /dev/null
+++ b/src/main/java/org/bukkit/plugin/java/annotation/permission/Permissions.java
@@ -0,0 +1,20 @@
+package org.bukkit.plugin.java.annotation.permission;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Part of the plugin annotations framework.
+ * <p>
+ * Represents a list of this plugin's registered name.
+ */
+
+@Documented
+@Retention(RetentionPolicy.SOURCE)
+@Target(ElementType.TYPE)
+public @interface Permissions {
+ Permission[] value() default {};
+}
diff --git a/src/main/java/org/bukkit/plugin/java/annotation/Description.java b/src/main/java/org/bukkit/plugin/java/annotation/plugin/Description.java
index 4595d06..4fd72ae 100644
--- a/src/main/java/org/bukkit/plugin/java/annotation/Description.java
+++ b/src/main/java/org/bukkit/plugin/java/annotation/plugin/Description.java
@@ -1,6 +1,9 @@
-package org.bukkit.plugin.java.annotation;
+package org.bukkit.plugin.java.annotation.plugin;
+import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
@@ -9,9 +12,10 @@ import java.lang.annotation.Target;
* Represents a short description for the plugin.
*/
+@Documented
+@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE)
public @interface Description {
-
- public String value();
+ String desc();
}
diff --git a/src/main/java/org/bukkit/plugin/java/annotation/LoadOn.java b/src/main/java/org/bukkit/plugin/java/annotation/plugin/LoadOn.java
index 9e5372d..3a63325 100644
--- a/src/main/java/org/bukkit/plugin/java/annotation/LoadOn.java
+++ b/src/main/java/org/bukkit/plugin/java/annotation/plugin/LoadOn.java
@@ -1,8 +1,11 @@
-package org.bukkit.plugin.java.annotation;
+package org.bukkit.plugin.java.annotation.plugin;
import org.bukkit.plugin.PluginLoadOrder;
+import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
@@ -11,8 +14,9 @@ import java.lang.annotation.Target;
* Represents the optional load order of the plugin.
*/
+@Documented
+@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE)
public @interface LoadOn {
-
- public PluginLoadOrder value();
+ PluginLoadOrder loadOn();
}
diff --git a/src/main/java/org/bukkit/plugin/java/annotation/LogPrefix.java b/src/main/java/org/bukkit/plugin/java/annotation/plugin/LogPrefix.java
index e8d6ed4..52bd424 100644
--- a/src/main/java/org/bukkit/plugin/java/annotation/LogPrefix.java
+++ b/src/main/java/org/bukkit/plugin/java/annotation/plugin/LogPrefix.java
@@ -1,6 +1,9 @@
-package org.bukkit.plugin.java.annotation;
+package org.bukkit.plugin.java.annotation.plugin;
+import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
@@ -9,8 +12,9 @@ import java.lang.annotation.Target;
* Represents the prefix used for the plugin's log entries, defaults to plugin name.
*/
+@Documented
+@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE)
public @interface LogPrefix {
-
- public String value();
+ String prefix();
}
diff --git a/src/main/java/org/bukkit/plugin/java/annotation/Main.java b/src/main/java/org/bukkit/plugin/java/annotation/plugin/Main.java
index ebef467..3a21c6c 100644
--- a/src/main/java/org/bukkit/plugin/java/annotation/Main.java
+++ b/src/main/java/org/bukkit/plugin/java/annotation/plugin/Main.java
@@ -1,9 +1,13 @@
-package org.bukkit.plugin.java.annotation;
+package org.bukkit.plugin.java.annotation.plugin;
+import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
+ * DEPRECATED: Use {@link Plugin} instead.
* Marks this class (which <i>must</i> subclass JavaPlugin) as this plugin's main class.
* <p>
* This class is part of the plugin annotation framework that automates plugin.yml.
@@ -23,25 +27,25 @@ import java.lang.annotation.Target;
* {@literal @}LogPrefix("Testing")
* {@literal @}LoadBefore("Essentials")
* {@literal @}Commands({
- * {@literal @}Cmd(
- * value = "foo",
- * desc = "Foo command",
+ * {@literal @}Command(
+ * name = "foo",
+ * name = "Foo command",
* aliases = {"foobar", "fubar"},
* permission = "test.foo",
* permissionMessage = "You do not have permission!",
* usage = "/<command> [test|stop]"
* ),
- * {@literal @}Cmd("bar")
+ * {@literal @}Command("bar")
* })
* {@literal @}Permissions({
* {@literal @}Perm(
- * value = "test.foo",
- * desc = "Allows foo command",
+ * name = "test.foo",
+ * name = "Allows foo command",
* defaultValue = PermissionDefault.OP,
* ),
* {@literal @}Perm(
- * value = "test.*",
- * desc = "Wildcard perm",
+ * name = "test.*",
+ * name = "Wildcard perm",
* defaultValue = PermissionDefault.OP,
* children = {"test.foo"}
* )
@@ -49,7 +53,10 @@ import java.lang.annotation.Target;
* public class Test extends JavaPlugin { ... }
* </code>
* </pre>
+ * @deprecated use {@link Plugin} instead.
*/
-
+@Deprecated
+@Documented
+@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE)
public @interface Main {}
diff --git a/src/main/java/org/bukkit/plugin/java/annotation/Name.java b/src/main/java/org/bukkit/plugin/java/annotation/plugin/Name.java
index 2ef196b..9a11752 100644
--- a/src/main/java/org/bukkit/plugin/java/annotation/Name.java
+++ b/src/main/java/org/bukkit/plugin/java/annotation/plugin/Name.java
@@ -1,6 +1,9 @@
-package org.bukkit.plugin.java.annotation;
+package org.bukkit.plugin.java.annotation.plugin;
+import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
@@ -9,10 +12,12 @@ import java.lang.annotation.Target;
* Represents the name of the plugin.
* <p>
* If not present in a class annotated with {@link Main} the name defaults to Class.getSimpleName() and will emmit a warning.
+ * @deprecated use {@link Plugin#name()} instead.
*/
-
+@Deprecated
+@Documented
+@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE)
public @interface Name {
-
- public String value();
+ String name();
}
diff --git a/src/main/java/org/bukkit/plugin/java/annotation/plugin/Plugin.java b/src/main/java/org/bukkit/plugin/java/annotation/plugin/Plugin.java
new file mode 100644
index 0000000..bd0a78f
--- /dev/null
+++ b/src/main/java/org/bukkit/plugin/java/annotation/plugin/Plugin.java
@@ -0,0 +1,24 @@
+package org.bukkit.plugin.java.annotation.plugin;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Documented
+@Retention(RetentionPolicy.SOURCE)
+@Target(ElementType.TYPE)
+public @interface Plugin {
+ /**
+ * The name of this plugin
+ */
+ String name();
+
+ /**
+ * This version of this plugin
+ */
+ String version();
+
+ String DEFAULT_VERSION = "v0.0";
+}
diff --git a/src/main/java/org/bukkit/plugin/java/annotation/plugin/UsesDatabase.java b/src/main/java/org/bukkit/plugin/java/annotation/plugin/UsesDatabase.java
new file mode 100644
index 0000000..aedb9e4
--- /dev/null
+++ b/src/main/java/org/bukkit/plugin/java/annotation/plugin/UsesDatabase.java
@@ -0,0 +1,20 @@
+package org.bukkit.plugin.java.annotation.plugin;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Part of the plugin annotations framework.
+ * <p>
+ * Denotes this plugin as using Bukkit's bundled database system.
+ * @deprecated Bukkit no longer supports database(s) in the plugin.yml
+ */
+
+@Deprecated
+@Documented
+@Retention(RetentionPolicy.SOURCE)
+@Target(ElementType.TYPE)
+public @interface UsesDatabase {}
diff --git a/src/main/java/org/bukkit/plugin/java/annotation/Version.java b/src/main/java/org/bukkit/plugin/java/annotation/plugin/Version.java
index 2d7ab66..ba8c25e 100644
--- a/src/main/java/org/bukkit/plugin/java/annotation/Version.java
+++ b/src/main/java/org/bukkit/plugin/java/annotation/plugin/Version.java
@@ -1,6 +1,9 @@
-package org.bukkit.plugin.java.annotation;
+package org.bukkit.plugin.java.annotation.plugin;
+import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
@@ -9,12 +12,15 @@ import java.lang.annotation.Target;
* Represents the version of the plugin.
* <p>
* If not present in a class annotated with {@link Main} the name defaults to "v0.0" and will emmit a warning.
+ * @deprecated use {@link Plugin#version()} instead
*/
+@Deprecated
+@Documented
+@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE)
public @interface Version {
+ String version();
- public String value();
-
- public static final String DEFAULT_VERSION = "v0.0";
+ String DEFAULT_VERSION = "v0.0";
}
diff --git a/src/main/java/org/bukkit/plugin/java/annotation/plugin/Website.java b/src/main/java/org/bukkit/plugin/java/annotation/plugin/Website.java
new file mode 100644
index 0000000..add83cf
--- /dev/null
+++ b/src/main/java/org/bukkit/plugin/java/annotation/plugin/Website.java
@@ -0,0 +1,20 @@
+package org.bukkit.plugin.java.annotation.plugin;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Part of the plugin annotations framework.
+ * <p>
+ * Represents the website of the plugin.
+ */
+
+@Documented
+@Retention(RetentionPolicy.SOURCE)
+@Target(ElementType.TYPE)
+public @interface Website {
+ String url();
+}
diff --git a/src/main/java/org/bukkit/plugin/java/annotation/Author.java b/src/main/java/org/bukkit/plugin/java/annotation/plugin/author/Author.java
index d226d7d..ef63a56 100644
--- a/src/main/java/org/bukkit/plugin/java/annotation/Author.java
+++ b/src/main/java/org/bukkit/plugin/java/annotation/plugin/author/Author.java
@@ -1,6 +1,10 @@
-package org.bukkit.plugin.java.annotation;
+package org.bukkit.plugin.java.annotation.plugin.author;
+import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
+import java.lang.annotation.Repeatable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
@@ -9,10 +13,10 @@ import java.lang.annotation.Target;
* Represents the author(s) of the plugin. Translates to {@code author}
* in plugin.yml if a single author, otherwise {@code authors}
*/
-
+@Documented
+@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE)
+@Repeatable(Authors.class)
public @interface Author {
-
- public String[] value();
-
+ String name();
}
diff --git a/src/main/java/org/bukkit/plugin/java/annotation/plugin/author/Authors.java b/src/main/java/org/bukkit/plugin/java/annotation/plugin/author/Authors.java
new file mode 100644
index 0000000..7e2673c
--- /dev/null
+++ b/src/main/java/org/bukkit/plugin/java/annotation/plugin/author/Authors.java
@@ -0,0 +1,14 @@
+package org.bukkit.plugin.java.annotation.plugin.author;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Documented
+@Retention(RetentionPolicy.SOURCE)
+@Target(ElementType.TYPE)
+public @interface Authors {
+ Author[] value();
+}