package org.bukkit.plugin; import java.io.InputStream; import java.io.Reader; import java.io.Writer; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.regex.Pattern; import org.bukkit.command.CommandExecutor; import org.bukkit.command.PluginCommand; import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.permissions.Permissible; import org.bukkit.permissions.Permission; import org.bukkit.permissions.PermissionDefault; import org.yaml.snakeyaml.Yaml; import org.yaml.snakeyaml.constructor.AbstractConstruct; import org.yaml.snakeyaml.constructor.SafeConstructor; import org.yaml.snakeyaml.nodes.Node; import org.yaml.snakeyaml.nodes.Tag; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; /** * This type is the runtime-container for the information in the plugin.yml. * All plugins must have a respective plugin.yml. For plugins written in java * using the standard plugin loader, this file must be in the root of the jar * file. *
* When Bukkit loads a plugin, it needs to know some basic information about * it. It reads this information from a YAML file, 'plugin.yml'. This file * consists of a set of attributes, each defined on a new line and with no * indentation. *
* Every (almost* every) method corresponds with a specific entry in the * plugin.yml. These are the required entries for every plugin.yml: *
name
* version
* main
* * Failing to include any of these items will throw an exception and cause the * server to ignore your plugin. *
* This is a list of the possible yaml keys, with specific details included in * the respective method documentations: *
| Node | *Method | *Summary | *
|---|---|---|
name |
* {@link #getName()} | *The unique name of plugin | *
version |
* {@link #getVersion()} | *A plugin revision identifier | *
main |
* {@link #getMain()} | *The plugin's initial class file | *
authorauthors |
* {@link #getAuthors()} | *The plugin contributors | *
description |
* {@link #getDescription()} | *Human readable plugin summary | *
website |
* {@link #getWebsite()} | *The URL to the plugin's site | *
prefix |
* {@link #getPrefix()} | *The token to prefix plugin log entries | *
load |
* {@link #getLoad()} | *The phase of server-startup this plugin will load during | *
depend |
* {@link #getDepend()} | *Other required plugins | *
softdepend |
* {@link #getSoftDepend()} | *Other plugins that add functionality | *
loadbefore |
* {@link #getLoadBefore()} | *The inverse softdepend | *
commands |
* {@link #getCommands()} | *The commands the plugin will register | *
permissions |
* {@link #getPermissions()} | *The permissions the plugin will register | *
default-permission |
* {@link #getPermissionDefault()} | *The default {@link Permission#getDefault() default} permission * state for defined {@link #getPermissions() permissions} the plugin * will register | *
awareness |
* {@link #getAwareness()} | *The concepts that the plugin acknowledges | *
* A plugin.yml example:
*/ public final class PluginDescriptionFile { private static final Pattern VALID_NAME = Pattern.compile("^[A-Za-z0-9 _.-]+$"); private static final ThreadLocal*name: Inferno *version: 1.4.1 *description: This plugin is so 31337. You can set yourself on fire. *# We could place every author in the authors list, but chose not to for illustrative purposes *# Also, having an author distinguishes that person as the project lead, and ensures their *# name is displayed first *author: CaptainInflamo *authors: [Cogito, verrier, EvilSeph] *website: http://www.curse.com/server-mods/minecraft/myplugin * *main: com.captaininflamo.bukkit.inferno.Inferno *depend: [NewFire, FlameWire] * *commands: * flagrate: * description: Set yourself on fire. * aliases: [combust_me, combustMe] * permission: inferno.flagrate * usage: Syntax error! Simply type /<command> to ignite yourself. * burningdeaths: * description: List how many times you have died by fire. * aliases: [burning_deaths, burningDeaths] * permission: inferno.burningdeaths * usage: | * /<command> [player] * Example: /<command> - see how many times you have burned to death * Example: /<command> CaptainIce - see how many times CaptainIce has burned to death * *permissions: * inferno.*: * description: Gives access to all Inferno commands * children: * inferno.flagrate: true * inferno.burningdeaths: true * inferno.burningdeaths.others: true * inferno.flagrate: * description: Allows you to ignite yourself * default: true * inferno.burningdeaths: * description: Allows you to see how many times you have burned to death * default: true * inferno.burningdeaths.others: * description: Allows you to see how many times others have burned to death * default: op * children: * inferno.burningdeaths: true *
* In the plugin.yml, this entry is named name.
*
* Example:
* * @return the name of the plugin */ public String getName() { return name; } /** * Gives the version of the plugin. *name: MyPlugin
/version PluginName
*
* In the plugin.yml, this entry is named version.
*
* Example:
* * @return the version of the plugin */ public String getVersion() { return version; } /** * Gives the fully qualified name of the main class for a plugin. The * format should follow the {@link ClassLoader#loadClass(String)} syntax * to successfully be resolved at runtime. For most plugins, this is the * class that extends {@link JavaPlugin}. *version: 1.4.1
org.bukkit.plugin, and your class
* file is called MyPlugin then this must be
* org.bukkit.plugin.MyPlugin
* org.bukkit. as a base package for
* any class, including the main class.
*
* In the plugin.yml, this entry is named main.
*
* Example: *
* * @return the fully qualified main class for the plugin */ public String getMain() { return main; } /** * Gives a human-friendly description of the functionality the plugin * provides. *main: org.bukkit.plugin.MyPlugin
/version PluginName
*
* In the plugin.yml, this entry is named description.
*
* Example: *
* * @return description of this plugin, or null if not specified */ public String getDescription() { return description; } /** * Gives the phase of server startup that the plugin should be loaded. *description: This plugin is so 31337. You can set yourself on fire.
STARTUP, but a dependency loads
* at POSTWORLD, the dependency will not be loaded before
* the plugin is loaded.
*
* In the plugin.yml, this entry is named load.
*
* Example:
* * @return the phase when the plugin should be loaded */ public PluginLoadOrder getLoad() { return order; } /** * Gives the list of authors for the plugin. *load: STARTUP
/version PluginName
* authors must be in YAML list
* format.
*
* In the plugin.yml, this has two entries, author and
* authors.
*
* Single author example: *
* Multiple author example: *author: CaptainInflamo
* When both are specified, author will be the first entry in the list, so * this example: *authors: [Cogito, verrier, EvilSeph]
author: Grum
*authors:
*- feildmaster
*- amaranth
* Is equivilant to this example:
* authors: [Grum, feildmaster, aramanth]* * @return an immutable list of the plugin's authors */ public List
/version PluginName
*
* In the plugin.yml, this entry is named website.
*
* Example: *
* * @return description of this plugin, or null if not specified */ public String getWebsite() { return website; } /** * Gives a list of other plugins that the plugin requires. *website: http://www.curse.com/server-mods/minecraft/myplugin
depend,
* creating a network with no individual plugin does not list another
* plugin in the network,
* all plugins in that network will fail.
* depend must be in must be in YAML list
* format.
*
* In the plugin.yml, this entry is named depend.
*
* Example: *
depend:
*- OnePlugin
*- AnotherPlugin
*
* @return immutable list of the plugin's dependencies
*/
public Listsoftdepend must be in YAML list
* format.
*
* In the plugin.yml, this entry is named softdepend.
*
* Example: *
* * @return immutable list of the plugin's preferred dependencies */ public Listsoftdepend: [OnePlugin, AnotherPlugin]
loadbefore must be in YAML list
* format.
*
* In the plugin.yml, this entry is named loadbefore.
*
* Example: *
loadbefore:
*- OnePlugin
*- AnotherPlugin
*
* @return immutable list of plugins that should consider this plugin a
* soft-dependency
*/
public List
* In the plugin.yml, this entry is named prefix.
*
* Example:
* * @return the prefixed logging token, or null if not specified */ public String getPrefix() { return prefix; } /** * Gives the map of command-name to command-properties. Each entry in this * map corresponds to a single command and the respective values are the * properties of the command. Each property, with the exception of * aliases, can be defined at runtime using methods in {@link * PluginCommand} and are defined here only as a convenience. *prefix: ex-why-zee
| Node | *Method | *Type | *Description | *Example | *
|---|---|---|---|---|
description |
* {@link PluginCommand#setDescription(String)} | *String | *A user-friendly description for a command. It is useful for * documentation purposes as well as in-game help. | *description: Set yourself on fire |
*
aliases |
* {@link PluginCommand#setAliases(List)} | *String or List of * strings | *Alternative command names, with special usefulness for commands
* that are already registered. Aliases are not effective when
* defined at runtime, so the plugin description file is the
* only way to have them properly defined.
* * Note: Command aliases may not have a colon in them. |
* Single alias format:
* or * multiple alias format: *aliases: combust_me aliases: [combust_me, combustMe] |
*
permission |
* {@link PluginCommand#setPermission(String)} | *String | *The name of the {@link Permission} required to use the command. * A user without the permission will receive the specified * message (see {@linkplain * PluginCommand#setPermissionMessage(String) below}), or a * standard one if no specific message is defined. Without the * permission node, no {@link * PluginCommand#setExecutor(CommandExecutor) CommandExecutor} or * {@link PluginCommand#setTabCompleter(TabCompleter) * TabCompleter} will be called. | *permission: inferno.flagrate |
*
permission-message |
* {@link PluginCommand#setPermissionMessage(String)} | *String | *
|
* permission-message: You do not have /<permission> |
*
usage |
* {@link PluginCommand#setUsage(String)} | *String | *This message is displayed to a player when the {@link * PluginCommand#setExecutor(CommandExecutor)} {@linkplain * CommandExecutor#onCommand(CommandSender,Command,String,String[]) * returns false}. <command> is a macro that is replaced * the command issued. | ** It is worth noting that to use a colon in a yaml, like *usage: Syntax error! Perhaps you meant /<command> PlayerName? `usage: Usage: /god [player]', you need to
* surround
* the message with double-quote:
* usage: "Usage: /god [player]" |
*
commands', while each individual command name is
* indented, indicating it maps to some value (in our case, the
* properties of the table above).
* * Here is an example bringing together the piecemeal examples above, as * well as few more definitions:
*commands:
* flagrate:
* description: Set yourself on fire.
* aliases: [combust_me, combustMe]
* permission: inferno.flagrate
* permission-message: You do not have /<permission>
* usage: Syntax error! Perhaps you meant /<command> PlayerName?
* burningdeaths:
* description: List how many times you have died by fire.
* aliases:
* - burning_deaths
* - burningDeaths
* permission: inferno.burningdeaths
* usage: |
* /<command> [player]
* Example: /<command> - see how many times you have burned to death
* Example: /<command> CaptainIce - see how many times CaptainIce has burned to death
* # The next command has no description, aliases, etc. defined, but is still valid
* # Having an empty declaration is useful for defining the description, permission, and messages from a configuration dynamically
* apocalypse:
*
* Note: Command names may not have a colon in their name.
*
* @return the commands this plugin will register
*/
public Map{} ) may be used (as a null value is not
* accepted, unlike the {@link #getCommands() commands} above).
* * A list of optional properties for permissions: *
| Node | *Description | *Example | *
|---|---|---|
description |
* Plaintext (user-friendly) description of what the permission * is for. | *description: Allows you to set yourself on fire |
*
default |
* The default state for the permission, as defined by {@link
* Permission#getDefault()}. If not defined, it will be set to
* the value of {@link PluginDescriptionFile#getPermissionDefault()}.
* * For reference:
|
* default: true |
*
children |
* Allows other permissions to be set as a {@linkplain
* Permission#getChildren() relation} to the parent permission.
* When a parent permissions is assigned, child permissions are
* respectively assigned as well.
*
* Child permissions may be defined in a number of ways:
|
* As a list:
* * Or as a mapping: *children: [inferno.flagrate, inferno.burningdeaths]
* An additional example showing basic nested values can be seen
* here.
* |
*
permissions', while each individual permission name is
* indented, indicating it maps to some value (in our case, the
* properties of the table above).
* * Here is an example using some of the properties:
*permissions:
* inferno.*:
* description: Gives access to all Inferno commands
* children:
* inferno.flagrate: true
* inferno.burningdeaths: true
* inferno.flagate:
* description: Allows you to ignite yourself
* default: true
* inferno.burningdeaths:
* description: Allows you to see how many times you have burned to death
* default: true
*
* Another example, with nested definitions, can be found here.
*
* @return the permissions this plugin will register
*/
public Listdefault node.
*
* In the plugin.yml, this entry is named default-permission.
*
* Example:
* * @return the default value for the plugin's permissions */ public PermissionDefault getPermissionDefault() { return defaultPerm; } /** * Gives a set of every {@link PluginAwareness} for a plugin. An awareness * dictates something that a plugin developer acknowledges when the plugin * is compiled. Some implementions may define extra awarenesses that are * not included in the API. Any unrecognized * awareness (one unsupported or in a future version) will cause a dummy * object to be created instead of failing. * *default-permission: NOT_OP
!@).
* awareness must be in YAML list
* format.
*
* In the plugin.yml, this entry is named awareness.
*
* Example:
awareness:
*- !@UTF8
*
* Note: Although unknown versions of some future awareness are
* gracefully substituted, previous versions of Bukkit (ones prior to the
* first implementation of awareness) will fail to load a plugin that
* defines any awareness.
*
* @return a set containing every awareness for the plugin
*/
public Set