Zetsyog

[WIP][*] Les plugins Bukkit

1 message dans ce sujet

Les plugins Bukkit


88x31.png
Cette uvre est mise à disposition selon les termes de laLicence Creative Commons Attribution - Pas dUtilisation Commerciale - Pas de Modification 3.0 non transposé. Tout partage implique que vous citiez l'auteur original.

 

-[INTRODUCTION]-

Hello World,

Je vais donc vous présenter un tutoriel sur les plugins Bukkit / Spigot,

qui est une API minecraft performante, même si plus limitée que le modding.

Pour réaliser ce tutoriel, il vous faudra donc :

- Des bases en programmation java

- Savoir utiliser son IDE pour ajouter des dépendances à ses projets

SQLIbrary, dePatPeter,pour les bases de données

 

-[SOMMAIRE]-

1]Préparation

A]Sans maven

B]Avec maven

C]Avec gradle

2]La base de notre plugin

A]La classe principale

B]Le fichier plugin.yml

C]Exporter notre plugin

D]Importer un plugin

3]Les évènements

A]Enregistrer un évènement

B]Des-enregistrer un évènement

C]Créer un évènement

4]Les commandes

5]Manipuler les objets

A] Les blocs

B] Les items

C] ...

6]La configuration

7]Les bases de données

8]Programmer des taches

9]Importer d'autres plugins

10]Bonus : quelques actions pratiques

 

1] Préparation

A] Sans maven

Spoiler


Pour créer notre plugin, il suffit simplement d'ajouter la dépendance de bukkit, qui est donc utilisée par CraftBukkit et Spigot. Pour ce faire allez sur le site officiel de bukkit et téléchargez la version de bukkit dont vous avez besoin. Maintenant, il vous suffit juste d'ajouter le jar que vous venez de télécharger à votre projet.


B] Avec maven

Spoiler


Si vous utilisez maven, vous pouvez ajouter le repo de bukkit en ajoutant dans votre pom.xml ces lignes-ci :


<project>
    [...]
    <repositories>
        [...]
        <!-- Lien vers le repository de bukkit -->
        <repository>
          <id>bukkit-repo</id>
          <url>http://repo.bukkit.org/content/groups/public/</url>
        </repository>
    </repositories>
    [...]
    <dependencies>
       [...]
        <!-- Ajout de la dépendance --> 
        <dependency>
            <groupId>org.bukkit</groupId>
            <artifactId>bukkit</artifactId>
            <scope>provided</scope>
            <!-- Ici la version que vous utilisez, changez si nécessaire
                 /!\ Attention : sur le repo maven, la dernière version disponible 
                     est la 1.7.9-R0.2 /!\          
             -->
             <version>1.7.2-R0.3</version>
        </dependency>
    </dependencies>
    [...]
</project>

 


C] Avec gradle

Spoiler


Vous pouvez faire de même pour gradle :


repositories {
    mavenCentral()
    maven {
        name "bukkit-repo"
        url "http://repo.bukkit.org/content/groups/public/"
    }
    [...]
}

dependencies {
    [...]
    compile "org.bukkit:bukkit:1.7.2-R0.3"
    [...]
}

 


2] La base de notre plugin

A] La classe principale

Spoiler


Pour que Bukkit reconnaisse notre plugin, il faut que notre classe principale soit fille de la classe JavaPlugin, qui nous donne donc accès à des méthodes pratiques.
Donc créons une nouvelle classe vide que je nommerait iciTutoPlugin, et on y ajoutera un simpleextends JavaPlugin


package fr.ironcraft.tuto;

import org.bukkit.plugin.java.JavaPlugin;

public class TutoPlugin extends JavaPlugin {

}

Bon nous avons un plugin mais pour l'instant, il ne fera rien.
Nous allons donc tout d'abord Override deux méthodes deJavaPlugin qui nous serons bien utiles plus tard. Je parle ici des méthodesonEnable etonDisable qui sont appelées respectivement lors de l'activation du serveur, et lors de son extinction.
Pour écrire dans la console, on va utiliser la classe Logger de Java, voici un code d'exemple :


package fr.ironcraft.tuto;

import org.bukkit.plugin.java.JavaPlugin;
import java.util.logging.Logger;

public class TutoPlugin extends JavaPlugin {

    private Logger logger;

    @Override
    public void onDisable() {
        logger = this.getLogger();

        logger.info("Plugin tuto activé !");
    }

    @Override
    public void onEnable() {
        logger.info("Plugin tuto désactivé !");
    }
}

Ici, ce code d'exemple n'affiche que des message lors de l'initialisation et la fermeture du serveur.
Bon tout laisse à penser que notre plugin est prêt à être lancé par un serveur, mais ce n'est pas le cas. En effet, il manque un fichier INDISPENSABLE au bon fonctionnement de notre plugin, il s'agit du fichierplugin.yml.

 

B] Le fichier plugin.yml

Spoiler


Le fichierplugin.yml est un simple fichier qui va permettre au serveur de lancer notre plugin. Il est donc indispensable et doit se situer à la racine de votre plugin, c'est-à-dire pas dans un package.
Donc créez ce fichier et mettez-y ces lignes qui sont déjà commentées.


name: ICTuto ## Le nom de votre plugin ##
author: Zetsyog ## Votre nom (celui de l'auteur) ##
## Si il y a plusieurs auteurs,
## utilisez cette ligne à la place
## authors: [Auteur1, Auteur2, Auteur3]
version: 1.0 ## La version de votre plugin ##
## La classe principale de votre plugin
## doit se présenter comme ça :
## package.classe
main: fr.ironcraft.tuto.TutoPlugin

Et voilà, vous avez votre plugin fonctionnel ! Il ne reste maintenant plus qu'a y ajouter des fonctionnalités cool !


C] Exporter notre plugin

Spoiler


Pour exporter votre plugin, exportez-le simplement en jar, ou via un maven clean. Et il ne vous reste plus qu'à mettre le jar précédemment généré dans le dossier plugins/ de votre serveur.


C] Importer un plugin

Spoiler


Vous pouvez avoir besoin d'un autre plugin pour développer le votre, comme par exemple d'un plugin pour utiliser les base de donnée. Je vais donc vous montrer comment installer SQLibrary (et comment l'utiliser dans le chapitre sur les bases de données).
Donc pour installer ce plugin, téléchargez-le sur sa page bukkit-dev, et ajoutez-le en tant que dépendance. Il possède aussi un repository maven :


[...]
<repository>
  <id>dakani</id>
  <name>Dakani Nexus Repo</name>
  <url>http://repo.dakanilabs.com/content/repositories/public</url>
</repository>
[...]
<dependency>
  <groupId>lib.PatPeter</groupId>
  <artifactId>SQLibrary</artifactId>
  <version>7.1</version>
</dependency>
[...]

Une fois cela fait, vous pouvez utiliser les bases de données avec ce plugin.
Mais il faut dire à bukkit que votre plugin dépends de SQLibrary, car il se peut qu'il charge votre plugin avant SQLibrary, ce qui provoquerais un belle erreur.
Donc il faut donc aller modifier votre plugin.yml cette ligne :


depend: [SQLibrary]

Cette ligne va s'occuper de dire à Bukkit qu'il faut d'abord charger SQLLibrary avant votre plugin, et si SQLibrary est manquant le serveur ne se lancera pas.

Il y a aussi une possibilité de faire des dépendances facultatives, c'est-à-dire que votre plugin fonctionne sans, mais qu'elles sont requises pour obtenir toutes les fonctionalitées de votre plugin. Evidemment, il faut encore les déclarer dans le plugin.yml


softdepend: [WorldEdit, WorldGuard, Plugin3] 

Pour toutes les dépendances il faut utiliser le nom du plugin inscrit dans leplugin.yml


3] Les évènements

Bukkit a une API d'évènement très développée qui est très pratique et nous permet d'influencer beaucoup de chose sur les actions qui se passent dans minecraft.

A] Enregistrer un évènement

Spoiler


Pour pouvoir utiliser ces évènements, il faut les "écouter", c'est-à-dire dire au serveur que l'on veut savoir quand une action est déclencher. Pour ce faire, il faut qu'une des classes de notre plugin implémente de l'interfaceListener. Après cela il faut dire à Bukkit que notre classe "écoute" les évènements grâce à la méthode registerEvents() duPluginManager. Cette méthode prends 2 arguments. Le premier est votre Listener, le second la classe de votre plugin. Pour accéder auPluginManager vous pouvez passer par la méthodeJavaPlugin.getServer().getPluginManager()ouBukkit.getPluginManager()
Ajoutez donc cette ligne dans la méthodeonEnable() :


this.getServer().getPluginManager().registerEvents(this, this);

Une fois cela fait il nous suffit de créer une méthode avec comme argument l'évènement qui nous interresse et l'annotation EventHandler.
Donc voici un code qui, lorsqu'un joueur interagit avec un objet (clic gauche ou droit), envoie un message à tous les joueurs du serveur avec les infos de ce joueur.


@EventHandler
public void onPlayerInterract(PlayerInteractEvent event) {
    // Faire quelque chose
}

L'annotationEventHandler peut avoir deux arguments :

  • priority :Doit être un EventPriority. Par défautEventPriority.NORMAL.La priorité de l'évènement (voir ci-dessous).
  • ignoreCancelled : C'est un boolean. Par défault false. S'il vaut true, la méthode ne sera pas appelée si l'évènement est annulé.

Les priorités d'évènement

Il y a 6 priorités d'évènement :

  • EventPriority.LOWEST
  • EventPriority.LOW
  • EventPriority.NORMAL
  • EventPriority.HIGH
  • EventPriority.HIGHEST
  • EventPriority.MONITOR

Elle servent juste à définir dans quel ordre sont appelés les différents évènements pour plusieurs plugins, car même si un évènement a été annulé, il sera quand même appelé dans d'autres plugins, qui peuvent actuellement le "désannuler".
Par exemple, pour l'évènement BlockPlace. Si un plugin, avec la priorité LOWEST, annule l'évènement, un second plugin avec une priorité NORMAL, va pouvoir le valider, et ainsi de suite pour les différentes priorités.
/!\Il est fortement déconseillé d'annuler ou de valider un évènement avec la priorité MONITOR, elle ne doit servir qu'à vérifier si un évènement a été annulé ou pas, comme pour un plugin de log./!\


B] Dés-enregistrer un évènement

Spoiler


Pour dés-enregistrer un évènement spécifique d'un listener ou d'un plugin on peut faire appel à la méthode Event.getHandlerList.unregister().
Exemple :


PlayerInteractEvent.getHandlerList().unregister(plugin);

Si on veut faire la même chose, mais pour tous les évènements d'un plugin on peut le faire comme ceci :


HandlerList.unregisterAll(plugin);

Sachez que ces deux méthodes peuvent avoir pour argument un plugin ou un listener.


C] Créer un évènement

Spoiler


Comme vous l'avez vu précédemment, les évènement ont tous une variable HandlerList.
Donc pour créer notre propre évènement, il faut d'abord que la classe soit fille d'Event et qu'elle contienne un static HandlerList. Voici un exemple d'évènement :


import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
 
public final class CustomEvent extends Event {
    private static final HandlerList handlers = new HandlerList();
    private String message;
 
    public CustomEvent(String example) {
        message = example;
    }
 
    public String getMessage() {
        return message;
    }
 
    public HandlerList getHandlers() {
        return handlers;
    }
 
    public static HandlerList getHandlerList() {
        return handlers;
    }
}

Une fois la classe de votre évènement créée, il vous suffit juste de, quand vous le souhaitez, dire a bukkit d'appeler votre event à tous les listeners disponibles. Voici le code correspondant :


// On instancie notre évènement
CustomEvent event = new CustomEvent("Sample Message");
// On "appele" l'évènement
Bukkit.getServer().getPluginManager().callEvent(event);

Une fois cela fait, vous pouvez, avec n'importe quel listener écouter cet évènement.
Cela peut être très pratique pour créer une API.


4] Les commandes

A] Créer une commande

Spoiler


Pour créer une commande, allez dans la classe de votre plugin et ajoutez cette méthode


@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
    return false;
}

Cette méthode sera appelée à chaque fois qu'une commande sera exécutée par un joueurou la console. C'est pour cela qu'elle prend en argument un CommandSender, qui peut être un joueur ou la console. Ensuite il y a le nom de la commande, label représente l'alias qui a été utilisé (on y reviendra plus tard) et enfin le tableau des arguments. Comme on peut le voir, cette méthode retourne un booléen qui définit si un message d'erreur est envoyé ou non au joueur, il est donc normal de laisser un return false à la fin de la méthode.
Donc, pour créer une simple commande nommée base, voici le code à mettre dans onCommand():


if(command.getName().equalsIgnoreCase("base"))
{
    // faire qqchose
    return true;
}
return false;

Ce code ne fais actuellement rien, mais si la commande /base est lancée, l'aide ne sera pas affichée.
Mais quelle aide me diriez-vous ? Eh bien, je vous ai un peu menti (oui c'est mal). En effet, si on testait actuellement notre plugin, et que l'on lancerait la commande /base, nous aurions une erreur comme quoi la commande n'existerait pas ! Et c'est normal. En effet, toutes nos commandes doivent être déclarées dans notreplugin.yml.
Donc nous allons ajouter ces lignes dans leplugin.yml.


commands:
   base:
      description: Commande de test !
      usage: /<command> [argument1]

Ici, base est le nom de la commande, description la description de votre commande, et usage est comment l'utiliser, sachant que <command> sera remplacé automatiquement par le nom de la commande.


B] Vérifier les commandes

Spoiler


Pour éviter les erreurs, il faudra ajouter quelques conditions à votre méthodeonCommand().
Par exemple, si vous votre commande n'est utilisable que par un joueur (un /give par exemple), voici à quoi votreonCommand()devrait ressembler


@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
    if(command.getName().equalsIgnoreCase("base"))
    {
        if(!(sender instanceof Player)){
            sender.sendMessage("Vous devez être un joueur pour utiliser cette commande !");
        } else {
            Player player = (Player) sender;
            // faire qqchose
            return true;
        }
    }
    return false;
}

Pour éviter lesArrayOutOfBoundsException, il faudra aussi vérifier la longueur des arguments :


@Override
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
    if (args.length > 4) {
        sender.sendMessage("Trop d'arguments !");
        return false;
    } 
    if (args.length < 2) {
        sender.sendMessage("Pas assez d'arguments !");
        return false;
    }
    // Faire qqchose
}

 


C] Utiliser un CommandExecutor séparé

Spoiler


Vérifier les commandes dans la classe de votre plugin, mais, si vous faites un jour un plugin assez grand, cela peut vite devenir illisible. C'est pour cela que l'on peut séparer les fichier qui execute vos commandes !
Pour ce faire, créez une nouvelle classe que nous appellerons BaseExecutor :


public class BaseExecutor implements CommandExecutor {
    private final TutoPlugin plugin;
 
    public MyPluginCommandExecutor(TutoPlugin plugin) {
        // on enregistre notre plugin au cas où on en aurais besoin
        this.plugin = plugin;
    }
 
    @Override
    public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
        // Faire qqchose
        return false;
    }
}

Et ensuite il faut déclarer que cette commande sera traitée dans une classe séparée, alors mettez ceci dans votre méthode onEnable() :


this.getCommand("base").setExecutor(new BaseExecutor(this));

Et voilà, vous savez à peu près tout ce qu'il y a à savoir sur les commandes. Il ne vous reste plus qu'à y ajouter des permissions.


5] Manipuler les objets

A] Les blocks

Spoiler


Donc ici nous allons voir comment modifier les blocks d'un monde depuis notre plugin. Par exemple, on veut que lorsque notre joueur utilise la commande /base, on veut que le block situé en dessous de lui devienne de la stone (vous pouvez utiliser n'importe quel block), voici comment s'y prendre. Le code est commenté, donc pas besoin de plus d'explication.


if(command.getName().equalsIgnoreCase("base"))
{
    if(!(sender instanceof Player)){
        sender.sendMessage("Vous devez être un joueur pour utiliser cette commande !");
    } else {
        // On récupère le joueur qui a lancé la commande
        Player player = (Player) sender;
        // On récupère sa position (un objet Location qui contient beaucoup d'informations)
        Location location = player.getLocation();
        // On prend la position un block en dessous
        location.setY(location.getBlockY() - 1);
        // On récupère le block coresspondant et on le remplace par de la stone
        location.getBlock().setType(Material.STONE);
        // On envoie un message au joueur pour lui dire que la commande a bien été effectuée !
        player.sendMessage("La commande marche !");
        return true;
    }
}
return false;

Bon vous savez désormais manipuler un block, mais comment faire pour remplir une zone entière, pour générer des bâtiments ou autre ? Il faut simplement utiliser des boucles for. Exemple d'une méthode, qui remplie tout les blocks dans un cube, délimitée par un coin et la longueur d'une arête.


public void fill(Location location, int length, Material material) {
    int bx = location.getBlockX();
    int by = location.getBlockY();
    int bz = location.getBlockZ();

    int lx = bx + length;
    int ly = by + length;
    int lz = bz + length;

    World world = location.getWorld();

    for(int x = bx; x < lx; x++) {
        for(int y = by; y < ly; y++) {
            for(int z = bz; z < lz; z++) {
                Block block = world.getBlockAt(x, y, z);
                block.setType(material);
            }
        }
    }
}

Et voici un exemple d'utilisation


if(command.getName().equalsIgnoreCase("base"))
{
    if(!(sender instanceof Player)){
        sender.sendMessage("Vous devez être un joueur pour utiliser cette commande !");
    } else {
        // On récupère le joueur qui a lancé la commande
        Player player = (Player) sender;
        // On récupère sa position (un objet Location qui contient beaucoup d'informations)
        Location location = player.getLocation();
        // On décale de 1 block la zone qui va être modifiée
        // Pour éviter d'asphyxier le joueur
        location.setX(location.getBlockX() + 1);
        // On remple la zone de stone
        this.fill(location, 5, Material.STONE);

        // On envoie un message au joueur pour lui dire que la commande a bien été effectuée !
        player.sendMessage("La commande marche !");
        return true;
    }
}
return false;

Le cas des panneaux

Les panneaux sont des blocks très pratiques dans minecraft, mais leur manipulation via un plugin est du coup un peu plus avancée.
Donc pour créer des panneaux, avec bukkit, il suffit de changer le type du block souhaité (utilisez Material.SIGN_POST, Material.SIGN représente un panneau dans l'inventaire (ItemStack). Mais ce panneau n'aura rien d'écrit dessus. Pour l'éditer, il faut simplement récupérer "l'état actuel" du block, via la méthodeBlock.getState(), et le cast enSign, qui nous permet d'en modifier le contenu.
Voici un code d'exemple commenté qui pose un panneau avec le nom du joueur à sa position (n'oubliez pas d'enregistrer la commande si vous utilisez ce code) :

 


if(command.getName().equalsIgnoreCase("base2")) {
    if(!(sender instanceof Player)){
        sender.sendMessage("Vous devez être un joueur pour utiliser cette commande !");
    } else {
        // On récupère le joueur qui a lancé la commande
        Player player = (Player) sender;
        // On récupère le block qui se situe au même endroit que le joueur
        Block block = player.getWorld().getBlockAt(player.getLocation());
        // On le change en panneau
        block.setType(Material.SIGN_POST);
        // On récupère "l'état" du block
        // Et on le cast en Sign
        Sign sign = (Sign)block.getState();
        // On en modifie les lignes (de 0 à 3)
        sign.setLine(0, "[Owner]");
        sign.setLine(1, player.getName());
        // On met à jour le panneau
        sign.update();
        return true;
    }
}

 


B] Les items

Spoiler


Tout d'abord, il faut savoir que les objets dans les inventaires minecraft sont représentés par la classe ItemStack. Celle-ci a de nombreuses fonctions très utiles et plusieurs constructeurs. Voici la listes de ses constructeurs (non dépréciés) :

  • ItemStack(Material material), le Material de l'objet (voir ci-après)
  • ItemStack(Material materail, int amount), encore une fois le Material de l'objet, ainsi que son nombre dans le stack.
  • ItemStack(Material material, int amount, short damage), pareil que dessus, avec la durabilité en plus, notion définie ci-après
  • ItemStack(ItemStack itemStack), crée un ItemStack, à identique à celui passé en argument

Tout d'abord, il y a quelques notions à définir : le Material est tout simplement le type de l'objet (dirt, épée, patate, ...), il en existe un pour tout les objets possible à avoir en inventaire en vanilla. Ils sont tous définis en static dans la classe org.bukkit.Material. Je n'ai rien à redire sur le amount. En revanche, le paramètre short damage, lui correspond à la "durabilité" de l'objet (vous savez, la petite barre verte en dessous de l'item, qui indique si votre mine va bientôt se détruire). Je dit bien "durabilité", car il est appelé comme ça dans le code, mais il s'agit plutôt à l'endommagement. En effet, plus cette valeur est haute, plus l'objet sera endommagé, jusqu'à atteindre une valeur maximum, définie dans le Material de l'item. Cette valeur sont modifiables via des setters.

Pour la modifier, il vous faut utiliser simplement les méthodes suivantes : ItemStack.setDurability(short) et ItemStack.getDurability().

Les enchantements


Pour ajouter des enchantements, il y a simplement des méthodes dans ItemStack. Les enchantements sont disponibles dans la classe Enchantment . Voici les méthodes utiles pour les enchantements.

  • ItemStack.addEnchantment(Enchantment, int), où le paramètre int définit le niveau d'enchantement.
  • ItemStack.removeEnchantment(Enchantment), qui retire l'enchantement spécifié s'il existe.
  • Map<Enchantment, Integer> getEnchantments(), qui retourne une map avec les enchantements et leur niveau correspondant.

Les ItemMeta


Touts les ItemStack ont une ItemMeta, qui est simplement un objet qui stock des informations utiles pour les items. Vous pouvez par exemple leur donner un nom personalisé. Pour récupérer l'objet ItemMeta, il suffit juste d'utiliser la méthode ItemStack.getItemMeta()Il existe également un setter.
L'objet ItemMeta vous permet de définir de nombreux paramètres de l'ItemStack.
Chose utile, on peut aussi ajouter des enchantements avec les ItemMeta, mais en plus, on peut ignorer la restriction du jeu.
Voici un code d'exemple qui change quelques paramètres:


ItemStack stack = new ItemStack(Material.BAKED_POTATO);
ItemMeta meta = stack.getItemMeta();
// On définit un lore custom
ArrayList<String> lore = new ArrayList<String>();
lore.add("Ceci est un item cheat");
lore.add("Ceci est une nouvelle ligne");
lore.add("Ceci en est une autre !");
meta.setLore(lore);
// On change le nom
meta.setDisplayName("Item cheat");

// On ajoute un enchantement (épine 15 ici)
meta.addEnchant(Enchantment.THORNS, 15, true);

// On met à jour l'ItemMeta
stack.setItemMeta(meta);

Qui vous donne une patate cuite avec pour nom ItemCheat et un enchantement thorns 15 (qui n'aura aucun effet, c'est une patate)


6] La configuration

Spoiler

Donc on va maintenant s'atteler aux configurations. Déjà à quoi ça sert une configuration ? Ca sert simplement à rendre votre plugin plus personalisable. Cela évite d'hardcoder (c-à-d de mettre des valeurs directement dans le code, sans modularité ni possibilité de les changer). Donc une config peut vous servir à pleins de chose, activer/désactiver des fonctions, changer des valeurs. Enfin bref c'est un petit plus qu'il ne faut pas négliger.

Pour commencer, je vais m'attaquer ici qu'aux configurations yml, dont une api est fournie par défaut.

Une configuration YML est représentée par l'object FileConfiguration, par lequel vous pourrez définir et récupérer pas mal de valeurs

A partir de cet objet, vous avez accès à des getters pour tout les types d'objets.


File configFile = new File("config.yml");
FileConfiguration conf = YamlConfiguration.loadConfiguration(configFile);

config.set("int", 3);
System.out.println(config.getInt("int"));
// Affiche 4

config.set("double", 3.14d);
System.out.println(config.getDouble("double"));
// Affiche 3.14

config.set("bool", false);
System.out.println(config.getBoolean("bool"));
// Affiche false

config.set("string", "yolo");
System.out.println(config.getString("string"));
// Affiche yolo

Bon c'est bien maintenant on sait rentrer et récupérer des valeurs dans une configuration. Il faudrait s'interresser à comment on l'enregistre.

En fait c'est très simple. L'object FileConfiguration a une méthode save(). Petit récap :


// On créer le fichier
File configFile = new File("config.yml");
FileConfiguration conf = YamlConfiguration.loadConfiguration(configFile);

// On le sauvegarde
conf.save();

En sachant qu'il existe des méthodes pour la config de base dans votre plugin : dans un fichier VotrePlugin/config.yml. Il est accessible via la méthode getConfig() de votre plugin. Vous pouvez aussi appeler la méthode saveDefaultConfig() qui écrasera l'ancienne config par le fichier config.yml situé à la racine de VOTRE JAR (avec le plugin.yml). Vous pouvez recharger cette config via la méthode reloadConfig().


7] Les bases de données

Spoiler

 


8] Programmer des taches

Spoiler

Les taches dans Bukkit sont des objets Runnable qui sont appelés lors de l'update du serveur.

Vous pouvez donc appeler une tache après un certain délais, ou répétée pendant un certain temps.

Vous pouvez appeler des tache synchronisée avec les serveur, c'est à dire appelées dans le même Thread, ou asyncrones, appelées dans un autre Thread. Gardez à l'esprit que les taches async ne doivent PAS accéder à l'api Bukkit.

Pour faire cela, vous utilisez le scheduler bukkit via Bukkit.getScheduler().

Exemple :


Bukkit.getScheduler().runTaskLater(plugin, new Runnable() {
    @Override
    public void run() {
        System.out.println("Hey en retard d'une seconde");
    }
}, 20);

Bukkit.getScheduler().runTaskTimer(plugin, new Runnable() {
    @Override
    public void run() {
        System.out.println("Je me répète toute les secondes !");
    }
}, 0, 20);

 

 


9] Importer d'autres plugins

Spoiler

 

 

 


10] Bonus

Spoiler

/** Coming soon **/

 

 

 

WIP


(Le plan n'est peut être pas définitif, je verrais au fur à a mesure que je rédige, comme il y a beaucoup de choses à dire, et je ne sais pas si je ne le ferais pas d'ailleurs en plusieurs topics)

PS: Il y a beaucoup de choses à dire, le tuto risque d'être long, et je n'ai pas trop de temps et il y les vacances qui arrivent, je pense qu'il sera fini pour la fin des vacances

EDIT 25/03 : je me remet à l'écriture de ce tuto, j'y ajouterais les idées que Géraud a gentiment proposées.

3

Partager ce message


Lien à poster
Partager sur d’autres sites

Créer un compte ou se connecter pour commenter

Vous devez être membre afin de pouvoir déposer un commentaire

Créer un compte

Créez un compte sur notre communauté. C’est facile !


Créer un nouveau compte

Se connecter

Vous avez déjà un compte ? Connectez-vous ici.


Connectez-vous maintenant