Welcome to the BukkitWiki!

This Wiki is home to Bukkit's documentation and regulations surrounding the Bukkit Project and it's services. Want to help out? We would love to have you! Signup to get started!

Plugin Tutorial/es

From BukkitWiki
Jump to: navigation, search

Introducción[edit | edit source]

Contents

Este gran tutorial pretende comenzar con el desarrollo de un plugin en Bukkit. Es imposible hacer un tutorial completo de todas las posibilidades de creación de un plugin en Bukkit, pero prefiero un resumen general de los conceptos básicos. Comience por asegurarse de que usted entiende Java, configurar su espacio de trabajo en un IDE presenta los elementos esenciales de la mayoría de plugins Bukkit.

Aprender Java[edit | edit source]

Estos tutoriales requieren conocimientos básicos del lenguaje de programación Java. Si acaba de empezar con Java o necesita un repaso, échele un vistazo a los siguientes links, le ayudarán enormemente! (Están en Inglés).

Los tutoriales de Oracle le ayudarán a entender el lenguaje de Java:

Videotutoriales JAVA[edit | edit source]

Los siguientes videotutoriales están en Inglés

El entorno de desarrollo[edit | edit source]

Antes de desarrollar un plugin (o aprendizaje de Java), usted necesitará configurar un entorno de desarrollo. Esto incluye pero no se limita a instalar un IDE (Integrated Development Environment). El siguiente tutorial contiene instrucciones para el IDE de Eclipse.

Para más información, vea Setting Up Your Workspace

Comenzando con el proyecto del plugin[edit | edit source]

Creando el Proyecto[edit | edit source]

Antes de empezar, usted necesitará configurar su espacio de trabajo y archivos en Eclipse. Inicie Eclipse, luego crear un nuevo proyecto seleccionando File > New > Java Project:

NewJavaProject.png

Nombrar al proyecto como usted quiera, luego ejecute el asistente de proyecto nuevo, siguiendo las instrucciones en pantalla. Una carpeta aparecerán en el panel explorador de paquete en el lado izquierdo; "izquierdo" en la pequeña flecha al lado de él para mostrar el contenido de su proyecto.

Referencia de la API de Bukkit[edit | edit source]

Antes de empezar a desarrollar tu plugin, usted necesitará agregar la biblioteca de la API de bukkit a su proyecto como un JAR externo. También puede añadir cualquier otra API que desea utilizar.

La ultima versión de la API de Bukkit puede descargarla de aquí: Bukkit API - Development Snapshot


Haga clic derecho sobre la carpeta con el nombre de su proyecto en el panel Package Explorer en el lado izquierdo de la pantalla y seleccione Properties . Luego seleccione Java Build Path en la caja de opciones a la izquierda. Haga clic en Add External JARs y navegue hasta donde descargaste la API de Bukkit.

BuildPathPic.png

Javadocs de Bukkit[edit | edit source]

Si usted tiene alguna experiencia con Eclipse y Java usted sabrá que cuando se pasa el ratón por encima de cualquier clase o método una caja amarilla aparecerá, conteniendo la documentación de esa clase o método. Esto se conoce como un Javadoc y también se puede acceder en línea desde Oracle website. Bukkit también tiene documentación que a menudo contiene descripciones útiles de cada método y clase proporcionada por la API, que está disponible aquí. Para tener esta información disponible dentro de Eclipse, primero haga clic derecho en el nombre del proyecto, luego haga click en Propiedades, luego en Javadoc Location y en el cuadro de texto que aparece escribir http://jd.bukkit.org/apidocs/. Debe quedar así:

Bukkitjavadocs.png

Haga clic en Validate y, a continuación, haga clic en Aceptar. ¡Ya está! Ahora los Javadocs de Bukkit están vinculados a la fuente Bukkit, y se puede acceder a la documentación útil desde dentro de Eclipse.

Creando un paquete[edit | edit source]

Ahora lo que necesita para crear un "paquete" que almacenará todos los archivos de clase Java que vamos a utilizar. Haga clic derecho sobre la carpeta "src" y seleccione New > Package

MakePackage.png

Nombre su paquete de la siguiente manera:

  • Si usted tiene un nombre de dominio, el paquete sería el nombre de dominio a la inversa.
    • Ejemplo: Si su dominio es: i-am-a-bukkit-developer.com Su paquete sería: com.i_am_a_bukkit_developer Fuente
    • Evite el uso de un dominio que no es suyo.
  • No tiene dominio? ¡Tienes otras opciones!
    1. Cree una cuenta en un sitio de control de código fuente, como github o SourceForge.
      • Para github, siga las instrucciones aquí y tendrá un sub-dominio, por lo que el paquete sería io.github.<nombredeusuario>
    2. Use su correo electrónico. Ejemplo: <nombredeusuario>@gmail.com sería com.gmail.<nombredeusuario>
    3. Este es el metodo menos recomendado... Solo tiene que utilizar cualquier nombre de paquete, una vez más, utilice esto como su último recurso.

Hay varias cosas que el paquete debe NO empezar:

  • org.bukkit
  • net.bukkit
  • com.bukkit
  • net.minecraft

Una vez que tenga el nombre del paquete base, tendrá que acabar con él con el nombre del plugin. Vamos a utilizar las páginas de ejemplo, github, para esto. Si va a crear un plugin llamado "TestPlugin" el nombre completo del paquete sería "io.github.<nombredeusuario>.Testplugin".

Creando la clase del plugin[edit | edit source]

Ahora que ya tenemos nuestro proyecto creado, podemos empezar a añadir archivos de clases y comenzar a hacer nuestro plugin. La clase principal del plugin es la clase que extiende el plugin de Java. Siempre debe haber una clase en tu plugin que extiende el plugin de Java directa o indirectamente. Siempre es una buena práctica para crear su primera clase principal y darle el mismo nombre que su plugin. Haga click derecho en el paquete que creó anteriormente y seleccione New > Class. Usted debe tener una nueva clase similar a la siguiente:

package {$TopLevelDomain}.{$Domain}.{$PluginName};

import org.bukkit.plugin.java.JavaPlugin;

public final class {$PluginName} extends JavaPlugin {
    
}
Warning Warning: Los plugins nunca debe invocar su constructor y crear nuevas instancias

Creando plugin.yml[edit | edit source]

Ahora que ha configurado el proyecto y la clase principal debe permitir que bukkit cargue el Plugin. Para eso debe crear el archivo plugin.yml. Este archivo contendrá la información esencial, y sin el, el plugin, no funcionará. Esta vez haremos click derecho en la carpeta raiz (La carpeta que tiene el mismo nombre que nuestro proyecto) Hacemos click derecho y presionamos New > File. En el cuadro de texto llamado File Name ingresamos "plugin.yml" Y luego Finish. Eclipse abrirá nuestro archivo nuevo automáticamente en el editor de texto predeterminado.

Pista: Si quieres mantener tu espacio de trabajo organizado, debe cerrar el editor de texto y arrastrar plugin.yml a la principal área de trabajo (a la derecha) y será capaz de editar el archivo dentro de eclipse.

Hay tres atributos esenciales que deben ser declarados en el plugin.yml:

name: El nombre de su Plugin
main: NOMBRE COMPLETO de la clase principal de su Plugin
version: La versión del Plugin

El archivo plugin.yml tendrá este aspecto:

name: {$PluginName}
main: {$PackageName}.{$MainClass}
version: {$VersionNumber}
Lightbulb.png Note: El nombre del paquete de plugins a menudo incluye el nombre del plugin, por lo que no se sorprenda de ver pluginname.pluginname al final de la segunda línea.
Lightbulb.png Note: Tu clase principal puede o no puede ser el nombre de su plugin en función de lo que usted nombró antes, ten en cuenta que distingue entre mayúsculas y minúsculas.

En este momento tu plugin puede ser cargado por Bukkit y se acompañará con las entradas del registro que indica esto, pero no hará nada!

onEnable() y onDisable()[edit | edit source]

Estos métodos se llaman cada vez que el plugin se habilita y deshabilita. De manera predeterminada su plugin va a permitir, de forma automática, hacer algo. Puede registrar los acontecimientos y proporcionar un cierto resultado de la depuración aquí. onEnable() se ejecuta cuando el plugin está habilitado, y debe contener la lógica para configurar el plug-in cuando está activado. onDisable() se ejecuta cuando un plugin está deshabilitado y debe contener la lógica para limpiar el lector y el estado asociado. Además, el plugin, puede reemplazar el onLoad() para realizar lógica adicional cuando se carga el plugin.

Introducción a onEnable() y onDisable()[edit | edit source]

Primero que nada debemos hacer los métodos onEnable() y onDisable() dentro de la clase principal creada en la sección anterior. Con esto podremos habilitar y deshabilitar nuestro plugin. Se debería ver como en las lineas siguientes:

package {$TopLevelDomain}.{$Domain}.{$PluginName};

import org.bukkit.plugin.java.JavaPlugin;

public final class {$PluginName} extends JavaPlugin {
    
    @Override
    public void onEnable() {
        // Insertar aquí la lógica para llevar a cabo cuando el plugin está habilitado.
    }
    
    @Override
    public void onDisable() {
        // Insertar aquí la lógica para llevar a cabo cuando el plugin está deshabilitado.
    }

}

Los métodos que existen ahora hacen que nuestro plugin pueda habilitarse y deshabilitarse cuando el servidor sea iniciado, reiniciado o apagado. Nota: El hacer una impresión que diga "{$PluginName} se ha habilitado!" no servirá de nada. Bukkit hará esto automáticamente.

Registrar un mensaje[edit | edit source]

Un plugin puede imprimir un mensaje en la consola y en el registro del servidor. Esto puede lograr invocando el método correcto de registrador del plugin. Primero debemos ejecutar el método getLogger() para recuperar el registrador asociado con este plugin. Entonces podemos empezar el registro. Vamos a escribir en el registro cuando se llama al método onEnable(). Podemos hacerlo insertando la siguiente línea en el método onEnable().

getLogger().info("onEnable se ejecuto correctamente!");

A continuación, puede hacer lo mismo en el interior de onDisable(), por lo que asegúrese de cambiar el mensaje.

Ahora, su clase principal, debe parecerse a esto:

package {$TopLevelDomain}.{$Domain}.{$PluginName};

import org.bukkit.plugin.java.JavaPlugin;

public final class {$PluginName} extends JavaPlugin {
		
	public void onEnable(){
		getLogger().info("onEnable se ejecuto correctamente!");
	}

	public void onDisable(){
		getLogger().info("onDisable se ejecuto correctamente!");
	}
}

Manejo del comando /reload[edit | edit source]

Es importante recordar que esto no sólo ocurre en el arranque y apagado del servidor, tu plugin también puede ser deshabilitado y habilitado por otros plugins o a través del uso del comando /reload mientras se ejecuta el servidor. Asumiendo que el servidor se ha iniciado sólo cuando está activado el plugin es, por lo tanto, una peligrosa suposición, como bien ya puede haber cargado de mundos de jugadores en línea, adicional, trozos adicionales cargados y muchas otras diferencias inesperadas.

Por ejemplo:

  • Tienes un plugin que almacena información sobre un jugador en un HashMap en el PlayerJoinEvent
  • Usted confía en tener esa información disponible para cada jugador.
  • Un operador utiliza el comando /reload.
  • Tu plugin se desactiva y todos los datos almacenados se pierde.
  • Tu plugin se activa nuevamente con varios jugadores ya online.
  • Estos jugadores no tienen ninguna información almacenada para ellos en el HashMap.
  • Intenta recuperar información sobre ellos, pero no hay ninguno!

Para que funcione correctamente en la recarga, debes encontrar a todos los jugadores actualmente en línea durante onEnable y almacenar la información correcta para ese jugador en el HashMap.

"Oyentes"[edit | edit source]

Los oyentes son clases cuyos métodos son invocados en respuesta a un evento. Todos los oyentes implementan org.bukkit.event.Listener. Para obtener más información sobre la creación de los oyentes,

vea por favor: Event API Reference

Comandos[edit | edit source]

El método onCommand()[edit | edit source]

Así que ahora sabes cómo registrar eventos y hacer algo cuando suceden, pero ¿y si sólo quieres algo que pasará cuando se escribe un comando? Utilizas onCommand. Este código se ejecuta cada vez que un jugador tipos un comando precedido por el carácter "/". Por ejemplo escribiendo "/hola" llamaría el método onCommand. En este caso nada sucedería porque el comportamiento no ha sido programado.

Evite el uso de comandos que son las mismas que las que vienen con Bukkit. Por ejemplo el comando "/give" es utilizado ya por varios plugins, y si se implementa otro comando "/give", tu plugin será incompatible con esos otros plugins. Usted debe registrar sus comandos en plugin.yml del plugin o no se accionarán este método.

El método onCommand siempre debe devolver un valor booleano (true / false). Si el valor devuelto es verdadero no verás ningún evento notable. Sin embargo si devuelve false entonces el plugin volverá a tus archivos plugin 'usage: property' y mostrar un mensaje al usuario mostrando cómo usar el comando como se especifica en el plugin.yml archivo.

Cuando se usa onCommand, usted siempre debe registrar 4 parámetros.


  • CommandSender sender - ¿Quien envió el comando?
  • Command cmd - ¿El comando se ejecutó?
  • String commandLabel - El alias del comando que se ejecutó
  • String[] args - un array de argumentos adicionales, por ejemplo escribiendo /hola abc def pondría abc en args [0] y def en args [1]

Configurar el comando[edit | edit source]

public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args){
	if(cmd.getName().equalsIgnoreCase("basic")){ //Si el jugador ha escrito /basic entonces haga lo siguiente...
		// Hacer algo...
		return true;
	} //Si pasó la función devolverá true.
        // Si esto ha sucedido la función devolverá el valor false.
	return false; 
}

Al codificar la función onCommand siempre es recomendable que devuelva false al final de la función. Al devolver false se mostrará el diálogo de uso establecido en plugin.yml (ver más abajo). Si algo sale mal se mostrará el mensaje de ayuda esta manera. Al devolver un valor de la función se cerrará por lo que si usted vuelve true debajo de cualquier código no se ejecutará, a menos que está anidada una sentencia return en una sentencia if o similar.

El .equalsIgnoreCase("basic") sólo significa que no va a distinguir entre caracteres mayúsculas y minúsculas. Por ejemplo, la cadena "Básico" y "básico" lo interpreta como lo mismo.

Agregar un comando a Plugin.yml[edit | edit source]

Usted también deberá agregar el comando a su archivo plugin.yml. Agregue lo siguiente al final del plugin.yml:

commands:
   basico:
      description: Este es un comando de ejemplo.
      usage: /<command> [player]
      permission: <nombredelplugin>.basico
      permission-message: Usted no tiene <permiso>
  • basico - Nombre del comando.
  • description - Descripción del comando.
  • usage - El diálogo de ayuda que los usuarios verán cuando regrese falso en el onCommand. Escribir con claridad, para que otros puedan discernir lo que el comando es y cómo usarlo.
  • permission - Esto es utilizado por algunos plugins de ayuda para resolver los comandos para mostrar al usuario.
  • permission-message - Este es el mensaje cuando el jugador intenta pero no tiene permiso para utilizar el mando.

Tenga en cuenta que los archivos yml utilizan 2 espacios para las pestañas, ya que el carácter de tabulación causará problemas.

Comandos de consola vs. Comandos del jugador[edit | edit source]

Usted puede haber notado el parámetro anterior CommandSender sender. CommandSender es una interfaz de Bukkit que tiene dos subclases útilidades (para los escritores de plugin) Player y ConsoleCommandSender.

Cuando usted está escribiendo su plugin, es una muy buena idea asegurarse de que los comandos que puede ejecutar desde la consola realmente funcionan, y que los comandos que sólo se deben ejecutar como un jugador registrado en verdad NO se pueden usar desde consola. Algunos plugins simplemente devuelven si el remitente no es un jugador (es decir, alguien trató de utilizar los comandos del plugin desde la consola), aunque estos comandos tienen sentido desde la consola (por ejemplo, el cambio del clima en el servidor).

Una forma de hacer esto es:

public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
	if (cmd.getName().equalsIgnoreCase("basico")){ //Si el jugador ha escrito /basico entonces haga lo siguiente...
		// Hacer algo...
		return true;
	} else if (cmd.getName().equalsIgnoreCase("basico2")) {
		if (!(sender instanceof Player)) {
			sender.sendMessage("Este comando sólo puede ser ejecutado por un jugador.");
		} else {
			Player player = (Player) sender;
			// Hacer algo...
		}
		return true;
	}
	return false;
}

En este ejemplo, el comando basico puede ser ejecutado por cualquier persona. Sin embargo, el comando basico2 sólo puede ser dirigido por los jugadores.

En general, se debe permitir que tantos comandos como sea posible para trabajar en la consola y para los jugadores. Los comandos que necesitan los jugadores pueden utilizar el mecanismo en el ejemplo anterior para comprobar que el CommandSender es en realidad un jugador antes de continuar. Tales comandos serían generalmente dependerá de algún atributo del jugador, por ejemplo, un comando de teletransporte necesita un jugador para teletransportarse, un elemento que da comando necesita un jugador para dar el artículo a ...

Si usted quiere estar más avanzado, podrías hacer algunas comprobaciones adicionales en sus argumentos de comando para que, por ejemplo, un comando de teleportación podría utilizarse desde la consola if and only if también se suministra el nombre de un jugador.

Usando una clase aparte de CommandExecutor[edit | edit source]

Los ejemplos anteriores sólo puso el método onCommand() en la clase principal del plugin. Para pequeños plugins, esto está bien, pero si escribes algo más extenso, tal vez tenga que poner su método onCommand() en su propia clase. Afortunadamente, esto no es demasiado difícil:

  • Crear una nueva clase dentro del paquete de su plugin. Llamarlo algo como MiPluginCommandExecutor (aunque por supuesto reemplazar MiPlugin con el nombre real de su plugin). Esa clase debe implementar la interfaz Bukkit CommandExecutor
  • En el método onEnable() de tu plugin , necesitas crear una instancia de su nueva clase de comando ejecutor y luego realizar una llamada como getCommand("basico").setExecutor(myExecutor); donde basico es el comando que queremos manejar, y myExecutor es la instancia que creamos.

Expliquemoslo con un ejemplo:

MyPlugin.java (La clase principal del Plugin):

@Override
public void onEnable() {
	// ...

	// Esto producirá un NullPointerException si no tienes el comando definido en el archivo plugin.yml.
	getCommand("basico").setExecutor(new MiPluginCommandExecutor(this));

	// ...
}

MiPluginCommandExecutor.java:

public class MiPluginCommandExecutor implements CommandExecutor {

	private MiPlugin plugin; // Puntero a la clase principal, no se requiere si no necesitas los métodos de la clase principal

	public MiPluginCommandExecutor(MiPlugin plugin) {
		this.plugin = plugin;
	}

	@Override
	public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
		//  	implementación exactamente igual que antes...
	}
}

Observe cómo pasamos una instancia del plugin principal al constructor para MyPluginCommandExecutor. Esto nos permite fácil acceso a los métodos de la principal del plugin si es necesario.

Al hacer esto, podemos organizar mejor nuestro código - si el principal onCommand() es grande y complejo, se puede dividir en submétodos sin abarrotar la clase principal del plugin.

Tenga en cuenta que si su plugin tiene varios comandos, tendrá que establecer el ejecutor de comandos para cada comando individual.

Escribiendo un onCommand seguro[edit | edit source]

Al escribir un onCommand, es importante que no comprometa la información, tales como el remitente de ser un jugador. Cosas a tener en cuenta:

Asegúrese de que el remitente es un jugador antes de emitir[edit | edit source]

Utilizando un simple código así lo hace posible:

public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args){
	if (sender instanceof Player) {
           Player player = (Player) sender;
           // Hacer algo...
        } else {
           sender.sendMessage("Usted debe ser un jugador!");
           return false;
        }
        // Hacer algo...
        return false;
}

Compruebe la longitud de los argumentos[edit | edit source]

No asumas siempre que el remitente escribió la cantidad correcta de argumentos!!

public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args){
	if (args.length > 4) {
           sender.sendMessage("Demasiados argumentos!");
           return false;
        } 
        if (args.length < 2) {
           sender.sendMessage("No hay suficientes argumentos!");
           return false;
        }
}

Al nombrar otro jugador por su nombre, asegúrese de que está en línea[edit | edit source]

A veces usted quiere conseguir otro jugador por el nombre introducido por el jugador. Asegúrese siempre de que el jugador está en línea!

public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args){
	Player target = (Bukkit.getServer().getPlayer(args[0]));
        if (target == null) {
           sender.sendMessage(args[0] + " no se encuentra online!");
           return false;
        }
        return false;
}

Si necesitas modificar un jugador actualmente qué no está en línea, la clase OfflinePlayer proporciona los métodos de manipulación básica.

Configuración del plugin[edit | edit source]

El API Bukkit proporciona una manera conveniente a los plugins gestionar los ajustes configurables por el usuario. Además también sirve como una manera fácil de almacenar datos.

Please see: Configuration API Reference

Permisos[edit | edit source]

Con la nueva API de Bukkit para permisos, no podría ser más fácil. Para averiguar si un jugador tiene un permiso especial utilice lo siguiente:

if(player.hasPermission("some.pointless.permission")) {
   //Hacer algo
}else{
   //Hacer otra cosa
}

También puedes consultar si un permiso se ha establecido o no (En Java llamado nulo) con la siguiente función:

boolean isPermissionSet(String name)

Te preguntarás por qué no hay ningún grupo. La respuesta es porque ellos no son realmente necesarios. Previamente uno de los principales usos de los grupos fue dar formato a los mensajes de chat. Sin embargo puede hacerse fácilmente con los permisos. Dentro de la configuración del plugin de tu chat definiría asociaciones entre permisos y prefijos. Por ejemplo, el permiso "someChat.prefix.admin" se correspondería con el prefijo [Admin]. Cuando un jugador habla con ese permiso su nombre llevará el prefijo con [Admin].

Otro uso común sería enviar un mensaje a todos los usuarios dentro de un grupo. Otra vez sin embargo esto se puede hacer con permisos con lo siguiente:

for(Player player: getServer().getOnlinePlayers()) {

    if(player.hasPermission("send.receive.message")) {
        player.sendMessage("Te enviaron un mensaje!!");
    }

}

Finalmente usted puede decir, bueno ¿cómo establecer y organizar los permisos del jugador si hay ningún grupo? Aunque la API de bukkit no proporciona grupos de sí mismo, debe instalar un plugin de proveedor de permiso como permissionsBukkit, groupmanager, etc. Para administrar los grupos para ti. Este API proporciona la interfaz, no la implementación.

Configuración de los permisos[edit | edit source]

Si desea más control sobre los permisos, por ejemplo, los valores por defecto o "hijos", entonces debería considerar añadir a su plugin.yml. Esto es completamente opcional, sin embargo se aconseja. A continuación se muestra un ejemplo de configuración de permisos que se añade al final de su actual plugin.yml:

permissions:
    portero.*:
        description: Acceso a todos los comandos de portero
        Hijo:
            portero.kick: true
            portero.ban: true
            portero.knock: true
            portero.denied: false
    doorman.kick:
        description: Permite expulsar a un usuario.
        default: op
    doorman.ban:
        description: Permite banear a un usuario.
        default: op
    doorman.knock:
        description: Llama a la puerta!
        default: true
    doorman.denied:
        description: Evita este usuario entre en la puerta

En primer lugar, cada permiso que tu plugin utiliza se define como un nodo secundario del nodo permisos. Cada permiso luego opcionalmente puede tener hijos, una descripción y un valor predeterminado.

Predeterminados[edit | edit source]

Por defecto, cuando un permiso no está definido para un jugador hasPermission devolverá false. Dentro de su plugin.yml puede cambiarse esta configuración del nodo predeterminado a ser uno de los cuatro valores:

  • true - El permiso será true de forma predeterminada. (Permitido).
  • false - El permiso será false de forma predeterminada. (NO permitido).
  • op - Si el jugador es OP entonces será true. (Permitido si es OP).
  • not op - Si el jugador no es OP entonces será true. (NO permitido si es OP).

"Hijos"[edit | edit source]

Antes de ahora es probable que se utilizará el * permiso para asignar automáticamente todos los sub-permisos. Esto ha cambiado con la API de bukkit y ahora puede definir los permisos secundarios. Esto permite mucha más flexibilidad. A continuación se muestra un ejemplo de cómo hacerlo:

permissions:
    portero.*:
        description: Acceso a TODOS los comandos de portero
        hijo:
            portero.kick: true
            portero.ban: true
            portero.knock: true
            portero.denied: false

Aquí el permiso de portero.* tiene varios permisos secundarios, o "hijos", que le asignamos. La manera que trabajan los permisos hijos es cuando portero.* se establece en true, el niño permisos se establecen en sus valores definidos en el plugin.yml. Sin embargo, si portero.* fue establecida en false podría invertirse todos los permisos de "hijo".

Establecer sus propios permisos[edit | edit source]

Si desea saber sobre el desarrollo de tus propios plugins de permisos, revisá el tutorial en Developing a permissions plugin.

Programación de tareas y tareas de fondo[edit | edit source]

Actualmente, los servidores de Minecraft operan casi toda la lógica del juego en un hilo, por lo que cada tarea individual que ocurre en el juego tiene que ser muy breves. Una pieza complicada de código en su plugin tiene el potencial de causar grandes retrasos y de retardo para los picos de la lógica del juego (Tambien llamado lagg), si no se maneja correctamente.

Por suerte, Bukkit tiene soporte para programar el código en tu plugin. Usted puede presentar una tarea ejecutable para ocurrir una vez en el futuro, o en forma recurrente, o usted puede girar en un subproceso independiente nuevo que puede realizar tareas largas en paralelo con la lógica del juego.

Hay un tutorial separado Scheduler Programming que introduce al programador y da más información sobre usarlo para programar tareas síncronas y dando inicio a las tareas asincrónicas en Bukkit.

Manipulación de bloques
[edit | edit source]

La forma más fácil de crear bloques es modificar un bloque existente. Por ejemplo, si desea cambiar el bloque que está ubicado a cinco bloques arriba, primero tendrías tu ubicación actual, agregar cinco a la coordenada actual, y luego cambiar. Por ejemplo:

public void onPlayerMove(PlayerMoveEvent event) {
    // Obtener la ubicación del jugador
    Location loc = event.getPlayer().getLocation();
    // Loc se establece en cinco bloques anteriores donde solía estar. Tenga en cuenta que esto no cambia la posición del jugador.
    loc.setY(loc.getY() + 5);
    World w = loc.getWorld();
    // Obtiene el bloque en la nueva ubicación.
    Block b = w.getBlockAt(loc);
    // Establece el bloque con ID 1 (Piedra)
    b.setTypeId(1);
}

El código anterior obtiene la ubicación del jugador, luego obtiene cinco bloques por encima de él y lo establece en piedra. Nota: Una vez que tienes un bloque, hay otras cosas que puedes hacer además de establecer su tipo. Para más información, consulte los JavaDocs.


Puede utilizar un concepto similar para generar edificios y bloques individuales mediante programación, mediante el uso de algoritmos. Por ejemplo, para generar un cubo sólido, podría utilizar bucles anidados for sobre un cubo entero y rellenarlo.

public void Generarcubo(Location loc, int length){
    // Set one corner of the cube to the given location.
    // Utiliza getBlockN() en lugar de getN() para evitar la proyección de un entero más tarde.
    int x1 = loc.getBlockX(); 
    int y1 = loc.getBlockY();
    int z1 = loc.getBlockZ();

    // Averiguar la esquina opuesta del cubo de la esquina y agregar longitud a todas las coordenadas.
    int x2 = x1 + length;
    int y2 = y1 + length;
    int z2 = z1 + length;

    World world = loc.getWorld();

    // Loop en el cubo en la dimensión x.
    for (int xPoint = x1; xPoint <= x2; xPoint++) { 
        //Loop en el cubo en la dimensión y.
        for (int yPoint = y1; yPoint <= y2; yPoint++) {
            // Loop en el cubo en la dimensión z.
            for (int zPoint = z1; zPoint <= z2; zPoint++) {
                // Obtener el bloque que estamos por Recorrer.
                Block currentBlock = world.getBlockAt(xPoint, yPoint, zPoint);
                // Establece el bloque de tipo 57 (bloque de diamante).
                currentBlock.setTypeId(57);
            }
        }
    }
}

Este método se construirá un cubo 3D o cuboides con la longitud dada y punto de partida. En cuanto a eliminar bloques simplemente seguir el mismo método para crearlas pero la ID se establece en 0 (aire).

Manipulación de inventario[edit | edit source]

Esta sección cubre sobre todo manipulación de inventario de jugador, pero lo mismo se aplica a la manipulación de inventario de cofres, si descubres cómo hacer inventario de un cofre :P. Aquí un simple ejemplo de manipulación de inventario:

public void onPlayerJoin(PlayerJoinEvent evt) {
    Player player = evt.getPlayer(); // El jugador que se unió
    PlayerInventory inventory = player.getInventory(); // El inventorio del jugador
    ItemStack itemstack = new ItemStack(Material.DIAMOND, 64); // Un stack de diamantes
        
    if (inventory.contains(itemstack)) {
        inventory.addItem(itemstack); // Agregar el stack.
        player.sendMessage("Bienvenido! Se le agrego un stack de diamantes!");
    }
}

Así que dentro de onPlayerJoin primero hacemos unas pocas variables para hacer nuestro trabajo más fácil: player, inventory y itemstack. El inventory es el inventario del jugador y itemstack es un ItemStack que tiene 64 diamantes. Después de eso, comprobamos si el inventario del jugador contiene un stack de diamantes. Si el jugador tiene un stack de diamantes, le damos otro stack con inventory.addItem(itemstack) y enviamos un mensaje. Manipular un inventario no es en realidad tan difícil, si queríamos podíamos quitar la pila de diamantes, simplemente cambiando inventory.addItem (itemstack) con inventory.remove (itemstack) y cambiar el mensaje un poco.

Manipulación de items[edit | edit source]

Tratándose de artículos en el código, se utiliza la clase ItemStack para buscar y configurar toda la información en esa pila.

Encantamientos[edit | edit source]

Para encantar a un elemento primero debes saber el [código de artículo http://www.minecraftwiki.net/wiki/Data_values] y el efecto ID. Los encantamientos mismos no pueden crear instancias (new Enchantment() no funciona) porque son abstractos, por lo que debe utilizar un EnchantmentWrapper. No se puede encantar objetos que normalmente no son encantables en SMP porque los servidores Bukkit no están configurados para enviar información de encantamientos de artículos no encantables. Así que no hay palos de fuego.


int itemCode = 280;  //utilizar el ID del artículo que usted quiere aquí.
int effectId = 20;  //utilizar el ID de encanto que usted quiere aquí.
int enchantmentLevel = 100; //Colocar el nivel de encantamiento aquí.

ItemStack myItem = new ItemStack(itemCode);  //Llamamos a la variable que trae el ID del ITEM
Enchantment myEnchantment = new EnchantmentWrapper(effectId);  //Llamamos a la variable que trae el ID del ENCANTAMIENTO
myItem.addEnchantment(myEnchantment, enchantmentLevel);  //Encantar item...

Metadatos[edit | edit source]

Bukkit está intentando hacer lo más fácil posible, desarrollo del plugin y HashMaps con clave de tipo de jugador, entidad, mundo o incluso un bloque fueron reemplazados por metadatos. Metadatos están una especie de alternativa a HashMap. Permite agregar los "campos" personalizados a los jugadores, Entidades, mundos y Bloques.

¿Por qué utilizar Metadatos?[edit | edit source]

Metadatos es todo manejado por Bukkit, lo que la hace muy buena alternativa a HashMaps.

Los Metadatos pueden utilizarse para compartir información entre plugins.

¿Por qué no utilizar metadatos?[edit | edit source]

-Un poco más difícil para obtener el valor. -No se guarda al apagar.

Consiguiendo & configurando metadatos[edit | edit source]

/* If you're having these methods in your plugin's main class (which extends JavaPlugin), you can remove parameters plugin from them, and in the FixedMetadataValue constructor and getMetadata method, use "this" instead*/
public void setMetadata(Player player, String key, Object value, Plugin plugin){
  player.setMetadata(key,new FixedMetadataValue(plugin,value));
}
public Object getMetadata(Player player, String key, Plugin plugin){
  List<MetadataValue> values = player.getMetadata(key);  
  for(MetadataValue value : values){
     if(value.getOwningPlugin().getDescription().getName().equals(plugin.getDescription().getName())){
        return value.value();
     }
  }
}

Nota: Si va a manipular con números, booleanos o cadenas, utilice el método conveniente para obtener el resultado. Por ejemplo, puede utilizar asInt, AsString o asBoolean en lugar del valor de averiguar el valor.

Bases de datos[edit | edit source]

Archivos planos a veces no son suficiente para lo que buscas hacer, Acá es cuando entran las bases de datos. Los motores de base de datos más comunes disponibles en máquinas Linux/Mac/Windows normalmente es SQL.

El software SQL permite crear bases de datos con columnas y rúbrica para identificar al contenido de cada celda. Considéralo como una hoja de cálculo con esteroides, donde todas las columnas definidas en su base de datos pueden aplicar reglas para asegurar la integridad. Además de ser más organizado que un archivo de datos personalizado simple, SQL proporciona un acceso más rápido y mejor ámbito de archivos planos.

MySQL[edit | edit source]

Otro motor de base de datos SQL popular se llama MySQL. Es más cercano al servidor-grado que SQLite, donde muchas empresas populares o sitios web depende de él para millones de visitas de la página web cada día. Con seguridad viene un poco más empinada curva de aprendizaje, porque MySQL tiene más parámetros regulables y capacidades.

La codificación para plugins acceder a MySQL sobre todo es lo mismo que tiny SQLite o mega-sized Oracle, con sólo pequeñas diferencias en la sintaxis de aquí o allá. Pero la administración tiene espacio para crecer. Quizá quieras configurar cuentas y privilegios dentro de la configuración de MySQL. Quizá quieras configurar scripts SQL que organizan tus backups y rollback a Estados anteriores.

Implementar el Plugin[edit | edit source]

Una vez que haya escrito el plugin, ¿cómo conseguir que a partir de una colección de archivos de código fuente en un archivo jar de trabajo que se puede instalar en un servidor? En primer lugar, establecer un servidor CraftBukkit en su máquina local. Para ello, visite la página wiki en Configurar un servidor. A continuación, tiene que exportar su plugin en un archivo. Jar de manera que se puede ejecutar en el nuevo servidor. Para ello, en Eclipse, haga clic en File > Export. En la ventana que aparece, en "Java", seleccione "JAR file" y haga clic en siguiente. Usted verá una ventana parecida a esta:

Eclipse export

A la izquierda, asegúrese de que está seleccionada la carpeta src. A la derecha, los dos archivos que comienzan con un punto decimal tienen que ver con Eclipse y no son importantes para su plugin, puede anular la selección. Es vital que plugin.yml se seleccione para que su plugin pueda trabajar. Exportar el archivo JAR a cualquier destino que quiera, pero asegúrese de que sabe dónde está.

El archivo jar que ha exportado ahora debe ser un trabajo plugin! asumiendo por supuesto que no hay ningún error en el código o el archivo plugin.yml. Ahora puede soltar el archivo jar ha exportado en la carpeta "plugins" de su servidor bukkit, volver a cargar o reiniciar el servidor, y probar de distancia! Para conectarse a un servidor que ejecuta localmente en el equipo, en pocas palabras "localhost" como la dirección IP del servidor de Minecraft multijugador. Si se encuentra con errores que no se puede resolver por sí mismo, trate de visitar el Foro de desarrollo de plugin, pregunta en la bukkitdev canal IRC o volver a leer este wiki. Una vez que tenga un plugin útil de trabajo, la posibilidad de presentar su proyecto de dev.bukkit para el consumo de la comunidad Bukkit.

Consejos y trucos[edit | edit source]

Prendiendo a un jugador fuego[edit | edit source]

La API de CraftBukkit es capaz de muchas cosas interesantes. Aquí están algunos fragmentos de código para algunos efectos agradables!

El siguiente código permite a un jugador que prendió fuego a otro jugador. Ejecutar un comando como /ignite Notch causaría la muesca que se prendió fuego.

@Override
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
    // Utiliza equalsIgnoreCase() sobre equals() para aceptar "encender" y "IgNiTe".
    if (cmd.getName().equalsIgnoreCase("ignite")) {
        // Asegúrese de que el jugador especificado exactamente un argumento (el nombre del jugador para encender).
        if (args.length != 1) {
            // Cuando onCommand() devuelve false, se muestra el mensaje de ayuda asociado con ese comando.
            return false;
        }

        // Asegúrese de que el remitente es un jugador.
        if (!(sender instanceof Player)) {
            sender.sendMessage("Sólo los jugadores pueden prender fuego con otros jugadores.");
            sender.sendMessage("Este es un requisito arbitrario sólo con fines de demostración.");
            return true;
        }

        // Conseguir el jugador que debe establecerse en fuego. Recuerda que indecies empezar con 0, no 1.
        Player target = Bukkit.getServer().getPlayer(args[0]);

        // Asegúrese de que el jugador esté en línea.
        if (target == null) {
            sender.sendMessage(args[0] + " no esta conectado!");
            return true;
        }

        // Establece el jugador en el fuego de 1000 ticks (hay ~ 20 ticks en el segundo, por lo que 50 segundos en total).
        target.setFireTicks(1000);
        return true;
    }
    return false;
}

Matar el jugador[edit | edit source]

Para seguir con el tema, aquí es una manera de matar el jugador.

Use esto para su método onCommand:

public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args){
    if(cmd.getName().equalsIgnoreCase("KillPlayer")){
        Player target = sender.getServer().getPlayer(args[0]);
        target.setHealth(0); 
    }
    return false;
}

Aquí es una extensión, que matará al jugador con una explosión:

float explosionPower = 4F; //Este es el poder de explosión - explosiones de TNT son 4F por defecto
Player target = sender.getWorld().getPlayer(args[0]);
target.getWorld().createExplosion(target.getLocation(), explosionPower);
target.setHealth(0);

Creando una explosión falsa[edit | edit source]

Este código produce los efectos de TNT/Creeper Visual y de Audio. Sin embargo, no hay daños de explosión se reparten a entidades o bloques. Esto es útil para desmejoras explosiones mientras se mantiene la estética de ellos.

@EventHandler
public void onExplosionPrime(ExplosionPrimeEvent event) {	
    Entity entity = event.getEntity();

    // Si el evento se cebó sobre TNT (TNT que está a punto de explotar), a continuación, haga algo
    if (entity instanceof TNTPrimed) {
        entity.getWorld().createExplosion(entity.getLocation(), 0);
    }
}

Esconde un jugador de otro jugador[edit | edit source]

Esto ocultará el jugador que ha usado este comando de un jugador especificado. Todo el mundo será capaz de ver el reproductor.

public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
    if(cmd.getName().equalsIgnoreCase("HideMe") && args.length == 1) {
        if (!(sender instanceof Player)) {
            sender.sendMessage("Sólo los jugadores pueden usar este comando!");
            return true;
        }
        // Después de comprobar para asegurarse de que el remitente es un jugador que, con seguridad nos podemos caso a uno.
        Player s = (Player) sender;

        // Obtiene el jugador que no debería ver el remitente.
        Player target = Bukkit.getServer().getPlayer(args[0]);
        if (target == null) {
            sender.sendMessage("Player " + args[0] + " is not online.");
            return true;
        }
        // Esconde un jugador determinado (s) de alguien (blanco).
        target.hidePlayer(s);
        return true;
    }
    return false;
}

Generar rayo donde está mirando el jugador[edit | edit source]

El código siguiente permite que cualquier jugador con una caña de pescar cree un rayo pulsando (y apuntando a algún lugar). Es un truco simple y divertido.

@EventHandler
public void onPlayerInteractBlock(PlayerInteractEvent event) {
    Player player = event.getPlayer();

    if (player.getItemInHand().getTypeId() == Material.FISHING_ROD.getId()) {
        // Crea un rayo de luz en un lugar determinado. En este caso, ese lugar es donde se ve el jugador.
        // Sólo se puede crear un rayo encima a 200 bloques.
        player.getWorld().strikeLightning(player.getTargetBlock(null, 200).getLocation());
    }
}

Solicitar sección[edit | edit source]

http://forums.bukkit.org/forums/plugin-requests.13/

Archivos de ejemplo y plantillas[edit | edit source]

Si tienes más preguntas sobre este tema, no dude en visitar el canal de BukkitDev IRC y pedir!

Language   EnglishбеларускаяDeutschespañolsuomifrançaisitaliano한국어Nederlandsnorsk bokmålpolskiportuguêsрусскийlietuviųčeština