Développer des plugins pour Craftbukkit

Statut
N'est pas ouverte pour d'autres réponses.

Ptibiscuit

Modérateur sucre vanillé
11 Mars 2011
620
25
13
Heypoday,

J'avais depuis longtemps envie de faire un tutoriel pour que les développeurs Java puisse créer leurs plugins. J'essayerai de donner un maximum de mon expérience pour que vous puissiez créer votre plugin facilement. Bien sur, les tutoriels ne seront pas suivis (A part les 3, 4 premiers). Ce seront surtout des "Comment ajouter des commandes ?", "Comment envoyer un message au serveur ?", ...

284.png
Tables des matières :
La formation de base
1. Les prèrequis​
2. Créer votre projet​
3. Les évènements​
Les autres chapitres :
1. La liste des évènements​
2. Envoyer un message à tous le monde et colorer le chat !​
3. Créer ses propres commandes​
4. Etre compatible avec Permissions​
5. Utiliser des Permissions (Nouvelle version)​
Les erreurs fréquentes :
1. Utiliser des références au objet Player​

Grid_Lava_Bucket.png
Les prèrequis :

Tout d'abord, il vous faudra connaître le Java. L'avoir pratiqué en ayant crée des programmes ou applications est un plus car vous saurez comment organisez votre code.
Si vous ne connaissez pas le Java, vous pouvez les tutoriels du Site Du Zéro, ils sont globalement bien, mais ils ne vous apprennent pas tous (Les énumerations, par exemple). Une expérience est toujours souhaitée. :)

Par ailleurs, mes screenshots seront prit avec l'environnement de travail Eclipse. Je vous le conseille véritablement, il vous fournit de nombreuses aides ainsi qu'un outil de déboggage puissant. Voici un petit tutoriel, toujours du Site Du Zéro, pour l'installer.

Grid_Lava_Bucket.png
La création d'un projet :

Si vous n'êtes pas étranger à Eclipse, vous saurez surement comment créer un projet. Seulement, pour que votre développement se fasse dans les meilleurs conditions possibles, nous devrons ajouter un .jar au classpath (Ce sera expliqué, ne vous inquiétez pas), vous devez donc télécharger l'outil de développement Bukkit. Mettez-le dans un de vos dossiers personnels et retenez sa position, vous en aurez besoin plus tard. :)

Donc, ouvrez Eclipse, allez dans Fichier => New => Project. Une fenêtre apparaîtra. Pour le nom du projet, vous pouvez mettre ce que vous voulez, seulement, dans ce tutoriel, notre premier plugin va être Menelas, le premier plugin que j'ai crée, particulièrement inutile. ;)
Si vous en connaissez pas Menelas, c'est un roi grecque qui a toujours voulu que tous ce qu'il touchait soit or. Son voeu fut exaucé, mais il mourut de faim car quand il voulait manger sa nourriture, elle devenu or.
Ce sera le but de notre plugin. Comme titre de projet, vous pouvez entrez "Menelas".

Ne faites pas "Finish", mais "Next", le projet va se créer et votre fenêtre va afficher autre chose. Cliquez sur l'onglet "Libraries" et appuyez sur "Add Externals Jars". Là, allez rechercher votre outil de développement Bukkit. :)
Je vous conseille de le mettre à une place bien précise et que tous les projets pointent vers le même .jar ! Pourquoi ? Quand Bukkit sortira une nouvelle version de l'API, vous remplacerez votre outil, et quand vous démarrerez Eclipse, vous verrez peut-être certains projets contenant des croix rouges, ça veut dire qu'un de vos plugins ne fonctionnera plus sur cette nouvelle version.

Une fois ceci fait, vous pouvez créez une classe (File => New => Class). Vous aurez une fenêtre comme ceci :
3ZKZ

Alors, passez "Source Folder", pour package, ça fonctionne un peu comme une URL mais à l'envers, à vrai dire, il n'y a pas d'obligation. Moi, j'écrit com.ptibiscuit.[NomDuPlugin], ça ne veut pas dire que j'ai un site appelé ptibiscuit.com ! :O
Retenez bien l'adresse, elle sera utile !
Pour name, vous pouvez mettre ce que vous voulez, sachez juste que ce sera votre classe principale, le contrôleur de votre plugin.
Généralement, les gens mettent le nom du plugin (Ici, "Menelas") ou encore "Core". Retenez-le, cela nous servira aussi ! :p
Une fois ces 2 champs remplies, vous pouvez Finish.
Vous aurez un code ressemblant à ceci :
Code:
package com.ptibiscuit.menelas;

public class Menelas {

}
Mais, vous devez faire hérité cette classe de JavaPlugin comme ceci :
Code:
package com.ptibiscuit.menelas;

import org.bukkit.plugin.java.JavaPlugin;

public class Menelas extends JavaPlugin {

}
JavaPlugin est une classe de Bukkit qui désigne le controleur d'un plugin. TOUT PLUGIN POSSEDE UNE CLASSE HERITEE DE JavaPlugin.
Vous aurez, normalement, une erreur, Menelas sera soulignée en rouge. Cliquez sur la croix rouge à gauche et appuyez sur "Add Unimplementeds Methods".
Votre code sera un peu plus gros, comme ceci :
Code:
package com.ptibiscuit.menelas;

import org.bukkit.plugin.java.JavaPlugin;

public class Menelas extends JavaPlugin {

@Override
public void onDisable() {
// TODO Auto-generated method stub

}

@Override
public void onEnable() {
// TODO Auto-generated method stub

}

}
Sachez que les méthodes onEnable() et onDisable() sont appelés respectivement à l’exécution du plugin et à la fermeture du plugin. Par exemple, quand un Op fait /reload, tous les onDisable() des plugins seront appelés, ensuite, tous les onEnable() des plugins seront appelés.

Avant de nous mettre à notre code, nous allons devoir créer un fichier manifeste. Pour ceci, faites Clic Droit sur la liste de vos projets, New => Untitled Text File, comme sur la photo ci-dessous :
3ZMh

(Vous noterez que ma classe contient une erreur signalée par la croix rouge, elle ne devrait pas. Si vous avez bien suivi toutes les opérations, votre classe devrait être nickel. :))

Dans le fichier nouvellement crée, vous devez mettre ce code :
name: [Nom du plugin]
main: [Adresse du package].[Nom de la classe heritée de JavaPlugin]
version: [Version]
website: [Votre site internet, faculfatif]
authors:
- [Nom d'un auteur]
- [Nom d'un autre auteur]
commands: [Laissez vide pour le moment]
Attention :
• Le nom du plugin désignera le nom du dossier qui vous sera donner dans /plugins, mettez donc le nom du plugin, sans espace, avec une majuscule à chaque mot.
• Pour l'adresse du Package et le nom de la classe, je vous ai demandée de les retenir, personnellement, c'est com.ptibiscuit.menelas.Menelas !
Menelas étant le nom de la classe héritée de JavaPlugin. :)
• Version, Website et auteurs ne sont pas très importants.
• Commands sera vue dans un prochain chapitre.

Une fois le fichier rempli, vous pouvez l'enregistrer en faisant Ctrl+S (Raccourci pour sauvegarder). Enregistrer-le dans le dossier de votre projet en le nommant plugin.yml.
Vous devriez avoir ça :
3ZNg


Voila, vous venez de créer un projet Bukkit. Enfaite, toutes les opérations que nous avons faites seront à faire pour chacun de vos plugins. En effet, chaque plugin a besoin d'une classe héritée de JavaPlugin et d'un fichier plugin.yml ! :)

Grid_Lava_Bucket.png
Les évènements :

La développement sous Bukkit ressemble beaucoup au Javascript : Tout repose sur des évènements.
Vous allez captez des évènements (Quand un joueur pose un bloc, Quand quelqu'un meurt, quand un joueur tape avec ou sans objet dans la main, ...). Par exemple, prenons un plugin bien connu : Permissions
Imaginons que je ne soit qu'un visiteur, et qu'il m'est interdit de détruire un bloc. Le code source ressemblera à :
Code:
Quand un joueur essaie de détruire un bloc,
Vérifier si il a la Permissions pour,
Si oui, on le laisse le casser,
Si non, on interrompt l'action.

Grid_Lava_Bucket.png
Assigner un bout de code à un évènement quelconque :

Pour notre plugin Menelas, nous allons capter l'évènement "onBlockDamage", quand un bloc prend des dommages.
Pour commencer, nous allons crée une classe, héritée de BlockListener. Le nom de cette classe importe peu (Perso, toutes mes classes héritées d'un Listener sont appellées []Manager, ici, ce sera BlockManager).
Dans cette classe, nous allons réécrire la méthode public void onBlockDamage(BlockDamageEvent e). Voici donc le code de notre nouvelle classe :
Code:
package com.ptibiscuit.menelas;

import org.bukkit.event.block.BlockDamageEvent;
import org.bukkit.event.block.BlockListener;

public class BlockManager extends BlockListener {

public void onBlockDamage(BlockDamageEvent e)
{
// Ce code sera executée quand un joueur tapera un bloc !
}
}
Alors, vous voyez qu'a l'appel de la fonction, nous recevrons un objet BlockDamageEvent, enfaite, pour chaque évènement on[QuelqueChose] vous avez un objet [QuelqueChose]Event, sachez que c'est comme ça partout, c'est une convention d'écriture. :)
Mais que contient cet objet ? Eh bah, allez voir ! Ecrivez, à la place du commentaire que j'ai marqué : e.
(Notez que le nom de l'objet BlockDamageEvent, e, n'importe peu !)
Normalement, Eclipse devrait vous afficher toutes les méthodes possibles appartenant à la classe BlockDamageEvent.
3ZOf

Les plus importantes sont celles qui commencent par get[...]().
Maintenant, réfléchissons un peu, qu'est-ce qui pourrait intervenir, quand un joueur tape sur un block. Le bloc en question et le joueur qui a tapé dessus !

En effet, vous avez les méthodes getPlayer() et getBlock(). Vous avez aussi d'autres méthodes, pour en savoir plus sur elle, vous pouvez consulter la Javadoc de Bukkit.
Que va faire notre plugin : Tout d'abord il va changer le type du bloc en bloc d'or, et il va envoyé un message à notre joueur pour le prévenir.
Faites e.getBlock(). ! Une nouvelle liste de méthodes apparaîtra :
3ZOw

Vous remarquerez la méthode setType(Material material) et setTypeId(Int id).
Alors, la première méthode attend enfaite une entrée d'une énumération de type Material. Pour Menelas, nous devons mettre le type de l'objet comme un block d'or, pour ceci tapez :
e.getBlock().setType(Material.
Vous aurez une liste de mot en majuscule qui apparaîtra, vous pourrez reconnaître tous les éléments du jeu !
3ZOW

Recherchez GOLD_BLOCK dans la liste. Ainsi, vous changerez le type du bloc tapé en bloc d'or.

Maintenant, nous avons une méthode e.getBlock().setTypeId(int id). Elle fait exactement la même chose sauf qu'elle fonctionne avec l'id du block (Block d'or = 41). Nous aurions pu mettre e.getBlock().setTypeId(41), ça aurait fait exactement la même chose que d'avoir utilisé setType(Material.GOLD_BLOCK)
Pourquoi avoir inventé ces 2 méthodes alors que setType(Material) est beaucoup plus pratique !
Si vous utilisez Itemcraft, il y aura de nouveaux objets (Par exemple, les pentes et coins de murs), ils ne seront pas consignées dans Material, vous devrez donc exclusivement utiliser leurs ids si vous voulez, par exemple, que chaque bloc touché devienne une pente en bois.
Voici le code de notre fonction :
Code:
public void onBlockDamage(BlockDamageEvent e)
{
// Ce code sera executée quand un joueur tapera un bloc !
e.getBlock().setType(Material.GOLD_BLOCK);
}

Maintenant, nous allons faire une deuxième chose, quand un bloc sera transformé de cette manière, il faudra que le joueur reçoivent un petit message. :)
Pour cela, faites .getPlayer(). , une liste des méthodes de Player vous sera affiché, choisissez sendMessage(String m), mettez un message pour avertir le joueur et concluez par le ; !
Voici donc le code :
Code:
public void onBlockDamage(BlockDamageEvent e)
{
// Ce code sera executée quand un joueur tapera un bloc !
e.getBlock().setType(Material.GOLD_BLOCK);
e.getPlayer().sendMessage("Ce bloc se change mystérieusement en bloc d'or !");
}

Voila, le code de notre classe est finie. Maintenant, nous devons avertir Bukkit que cette classe doit être avertie quand un bloc subit des dommages !

Grid_Lava_Bucket.png
Prèvenir Bukkit qu'il faut exécuter cette fonction à tel évènement :

Pour commencer nous allons instancier un objet de la classe BlockManager comme un attribut de la classe Menelas :
Code:
package com.ptibiscuit.menelas;

import org.bukkit.plugin.java.JavaPlugin;

public class Menelas extends JavaPlugin {

private BlockManager bm = new BlockManager();

@Override
public void onDisable() {
// TODO Auto-generated method stub

}

@Override
public void onEnable() {
// TODO Auto-generated method stub

}

}
Ensuite, nous devons prèvenir Bukkit que la classe BlockManager contient la réécriture de la fonction onBlockDamage(). Pour cela, nous devons utiliser la fonction PluginManager.registerEvent(...).
Dans la fonction onEnable(), utilisez la méthode getServer() qui est dans JavaPlugin, donc écrivez :
this.getServer()
Utilisez la méthode getPluginManager() de Server pour acquérir votre PluginManager et l'enregistrer dans une variable. :)
En tout ça donne :
Code:
PluginManager pm = this.getServer().getPluginManager();
Pour avertir Bukkit qu'il fat avertir BlockManager, il faut utiliser :
Code:
PluginManager pm = this.getServer().getPluginManager();
pm.registerEvent([TYPE], [LISTENER], [PRIORITE], [JAVAPLUGIN]);
Vous devez rentrer tous ces paramètres !
Pour le premier, vous devez utiliser l'énumération Event.Type. Faites Event.Type. pour voir la liste des évènements possibles :
3ZQH

Remarquez "BLOCK_DAMAGE", c'est celui qu'on cherche ! Séléctionnez-le. :)
Ensuite, le deuxième attend le Listener qui contient la fonction réécrite. Chez nous, c'est BlockManager, j'ai fait une instance de BlockManager que j'ai appellé bm, je mets donc bm.
Troisièmement, il faut une priorité. Pour en définir une, il faut utiliser l'énumération Priority. Comme d'habitude, faites Priority. pour voir la liste des priorités. Vous en avez 5, Lowest, Low, Normal, High, Highest. Généralement, à part pour cas spécifiques, vous pouvez mettre Priority.Normal. :)
Quatrièmement, vous devez mettre la classe héritée de JavaPlugin qui constitue votre plugin. Vu qu'on est en plein dedans, c'est this.
Au final, on a ceci :
Code:
pm.registerEvent(Event.Type.BLOCK_DAMAGE, bm, Priority.Normal, this);
Ainsi, quand le plugin sera démarré (onEnable()), on prévient le serveur qu'il faut appeler la fonction onDamageBlock() de BlockManager.

Et voila ! C'est fait, notre plugin est prêt à être lancé.

Grid_Lava_Bucket.png
Faire démarrer la bête :

Allez dans File => Export, sélectionnez JAR File, et vous aurez cette fenêtre :
3ZRB

Vous devez cocher le nom de votre projet, "Menelas", et donnez l'endroit ou le .jar sera crée. :)

Sur votre serveur, vous devrez placez votre .jar dans le dossier /plugins, et faire la commande /reload pour que votre serveur prenne en compte votre plugin. A vous d'essayer le plugin après ! Tapez un bloc et regarder ce que ça donne !

Autres chapitres :

Grid_Lava_Bucket.png
La liste des évènements :

Vous vous êtes surement posés la question, comment avoir la liste de tous les évènements possibles de Bukkit ? Grâce au tutoriel ci-dessus, vous connaissez onBlockDamage, mais il en existe bien, bien, bien plus !
Pour les connaitre, vous pouvez voir dans la Javadoc de Bukkit. Cette Javadoc doit être votre bible, elle contient tou, TOUT !
Pour connaître les listeners, vous pouvez rechercher toutes les classes qui finissent pas Listeners. Voici une petite liste :
PlayerListener, EntityListener, BlockListener, ServerListener, VehicleListener (Minecart, Bateau, ...), WeatherListener (Pluie, Neige, ...), WorldListener, RegisteredListener
Tous ces objets contiennent des on[...]. Il y en a beaucoup, moi même en faisant cette liste j'en ai découvert que je ne connaissais pas ! :p

Grid_Lava_Bucket.png
Envoyer un message au serveur et colorer le chat ! :

Pour envoyer un message à l'entièreté du serveur, vous devez utilisez la méthode broadcastMessage(String) de la classe Server. Pour accéder au serveur, vous devez faire :
Code:
Server s = this.getServer();
// Après, pour envoyer un message
s.broadcastMessage("Heyo !");

Pour colorer le chat, vous devez utilisez l'énumeration ChatColor, pour l'utilisez, vous devez le caster en String lors de l'envoie du message.
Par exemple, pour envoyer un message à un joueur en rouge :
Code:
[Player].sendMessage(ChatColor.RED + "Salut !" + ChatColor.WHITE);
Vous aurez remarquer que j'ai remis la couleur blanche à la fin de ma phrase. En effet, si vous ne le faites pas il se pourra que vous modifier la couleur du chat jusqu'à la fin.
Vous pouvez faire ChatColor. pour regarder toutes les couleurs disponibles. :)

Grid_Lava_Bucket.png
Créer ses propres commandes :

Pour créer ses commandes bukkit, vous avez 2 moyens de créer des commandes, sachez que ces 2 moyens sont toujours fonctionnel. C'est parfois d'ailleurs l'objet de débat ou de troll pour savoir lequel est le meilleur.
  • Soit vous utilisez des objets CommandExecutor en leur attribuant un nom de commande. Quand la commande sera demandé, l'objet qui implémente CommandExecutor attribué sur appelé.
    Cette méthode vous oblige à créer un objet qui implémente l'interface CommandExecutor à chaque fois que vous voulez créer une commande.
  • Soit vous réécrivez la méthode onCommand([...]) de JavaPlugin tout en ayant pris soin d'inscrire vos commandes dans le fichier plugin.yml. C'est cette méthode que l'on verra dans le tuto.
Pour commencer, ouvrez-le fichier plugin.yml, celui qu'on a crée au début du tuto. Si vous le lisez, vous verrez qu'à la fin, il y a "commands:".
En effet, nous allons renseigner nos commandes dans cette espace. Pour chaque commande que vous voulez créer, vous devez ajouter ceci après le "commands:" :
Code:
commands:
    [Nom]:
        description: [Description]
        usage: /[Nom] [Arguments ...]
    mremove:
        description: Enleve un joueur de la liste
        usage: /mremove <player>
    mban:
        description: Utilise pour bannir un joueur
        usage: /mban <player> <raison>
La première commande vous montre comment remplir les espaces, les 2 derniers sont des exemples tirés de Multiban. Attention à ne pas faire de faute dans le nom de la commande, car sinon, la méthode onCommand([...]) ne sera pas appelé.
Une fois votre fichier plugin.yml terminé, enregistrez et fermez-le.

Maintenant, retournons dans notre code. Dans l'objet hérité de JavaPlugin, vous allez réécrire une méthode de JavaPlugin. Ajoutez donc une méthode avec cette entête :
Code:
public boolean onCommand(CommandSender sender, Command command, String label, String[] args)
{

}
Premièrement, clarifions les choses. onCommand([...]) sera appelé quand quelqu'un entre une commande qui correspond à une des commandes écrites dans votre plugin.yml.
Donc, quand quelqu'un écrira /mban ..., onCommand([...]) sera appelé, mais quand quelqu'un fera /money, onCommand([...]) ne sera pas appelé car il n'est pas défini dans notre fichier plugin.yml

Reprenons les arguments de la fonction onCommand(CommandSender sender, Command command, String label, String[] args) :)
CommandSender est une interface, enfaite, sender représente la chose qui a appelé la commande (Vous pouvez appelez une commande depuis la console, je vous rappelle !).
Imaginons que vous voulez, quand le joueur fait la commande, enregistrez sa position. Vous allez d'abord devoir vérifier que sender est un joueur. C'est impossible d'enregistrer la position de la console. Voici donc le code qui vous permettra de faire ce test :
Code:
public boolean onCommand(CommandSender sender, Command command, String label, String[] args)
{
    if (sender instanceof Player)
          sender.sendMessage("Tu es bien un joueur :)");
    else
          sender.sendMessage("Il faut être un joueur pour éxécuter cette console.");
}
Le deuxième argument est un objet Command, pour connaître ses méthodes, rendez-vous dans la Javadoc de Bukkit. Mais très franchement, je ne l'ai jamais utilisé. ;P
Quand un joueur va taper une commande, imaginons :
/mban RandomSnake Parce qu'il est méchant.
Le 3ème argument sera le label de la commande, ici, il vaudra "mban". L'array de String args correspond à tous les mots en dehors du label, ici, nous aurons donc un array correspondant à {"RandomSnake", "Parce", "qu'il", "est", "méchant."}.
Si vous avez plus d'une commande dans le fichier plugin.yml, vous devrez donc vérifier, avec le label, quel fonction a été véritablement appelée.

Dernière chose, vous aurez remarqué que la fonction onCommand([...]) renvoie un boolean. Si la variable vaut true, cela veut dire que la commande a fonctionné comme il fallait. Si vous renvoyé false, Bukkit va afficher ce que vous avez marqué après usage: dans le fichier plugin.yml. :)

Quand vous aurez 5, 6 commandes, vous remarquerez la grandeur de la fonction onCommand(). En effet, il y aura un if(label.equals("nomDeCommand")) pour chaque commande qui contiendra aussi son traitement ! C'est l'une des arguments défavorables de l'utilisation de onCommand(), vous avez une grosse fonction qui contient tous les traitements de commande. Personnellement, ça ne me dérange pas, mais certaines personnes préfèrent avoir un objet hérité de CommandExecutor pour chaque commande crée.

Grid_Lava_Bucket.png
Etre compatible avec Permissions :

Pour rendre un plugin compatible avec Permissions, et donc pouvoir récupérer des Permissions depuis son plugin, vous devez téléchargez ce .jar et l'ajouter à vos librairies.
Permissions
Pour ceci, faites Clic-Droit sur le nom de votre projet dans la colonne de gauche, "Build Path" => "Add External Jar" => Choisissez le fichier Permissions.jar et confirmer. Ensuite, insérez ce code dans votre plugin :
Code:
public static PermissionHandler Permissions;

private boolean setupPermissions() {
        Plugin test = this.getServer().getPluginManager().getPlugin("Permissions");

        if (this.Permissions == null) {
            if (test != null) {
                this.Permissions = ((Permissions)test).getHandler();
                return true;

            } else {
                log.info("Permission system not detected, defaulting to OP");
                return false;
            }
        }
        return false;
    }
Ensuite, dans votre méthode onEnable(), vous devez ajouter cette ligne :
Code:
if (this.setupPermissions())
{
  // Le chargement de Permissions à réussi, vous pouvez l'utiliser
}
else
{
  // Le chargement n'a pas réussi, vous devez donc utiliser une autre façon pour votre plugin. (Utiliser les joueurs Op par exemple)
  // Attention, dans ce cas Permissions vaudra null, veillez à ne pas réveiller l'erreur NullPointerException !
}
Une fois que tous ceci est écrit, vous pouvez utiliser l'objet Permissions pour faire vos tests. Pour vérifier si quelqu'un possède une permission :
Code:
if (Permissions.has([Player], "plugin.node"))
La méthode renverra true si le joueur possède bien cette Permissions , à vous de créer vos propres noeuds de permissions que les administrateurs devront ajouter au fichier de config pour qu'ils puissent utiliser votre plugin. :)
D'autres méthodes sont possibles, malheureusement, la Javadoc de Permissions est morte, vous devez donc voir en faisant Permissions. pour voir la liste des méthodes disponibles.

Grid_Lava_Bucket.png
Utiliser des Permissions :


L'avènement de PermissionsBukkit, le module par défaut de Permissions de Bukkit, permet maintenant de gérer plus facilement les permissions. Seulement, avant de vous montrer comment faire, je vais vous expliquer l'histoire des Permissions dans Bukkit (Cela peut vous paraître dérisoire, mais ça permet de savoir quel Permissions vient de où et que fait tel plugin de Permissions).
Le premier plugin de Permissions fut Permissions ! :D
Il était complet, très fonctionnel, a reçu pas mal de mise à jours, et à même été l'objet d'ajout via d'autre plugins (comme PEX). Seulement, cela n'en est pas resté là. Un autre plugin de Permissions, GroupManager, a fait son apparition. Il se voulait plus complet, facile d'utilisation, et l'a été. Seulement, il était très ennuyant pour les développeurs de rendre compatible leurs plugins et pour Permissions et pour GroupsManager. On a du, donc, pendant une époque, vérifier à chaque quel type de plugin de Permissions était là, adapter les comportements, ...
Par après, un plugin nommé GroupBridge, a permis, enfaite, de simuler un plugin nommé Permissions. Enfaite, quand, dans votre plugin, vous faisier .getPlugin("Permissions"), GroupsBridge redirectionnait ceci vers GroupManager. Tout était parfait dans le meilleur des mondes.

Par après, Bukkit a voulu commoniser les Permissions en créant PermissionsBukkit. Seulement, ce plugin est très, très sommaire. Par exemple, vous ne pourrez pas changer le groupe d'un joueur (Ou alors de manière très sale), car la notion de groupe dans PermissionsBukkit n'existe tout simplement pas. (Les permissions sont données lors du démarrage du serveur aux joueurs selon leurs groupes. Ils ne font donc pas partis d'un groupe, dans le code, ils n'ont juste qu'une liste de Permissions)
Par ailleurs, pour éviter de reproduire le scénario d'avant, SuperPermsBridge, un plugin comme GroupBridge, permet de relier GroupManager et Permissions vers PermissionsBukkit quand un plugin le demandait.
Vous ne pourrez donc pas directement modifier les groupes avec PermissionsBukkit.

Revenons aux brefs de ce tutoriel, pour vérifier les Permissions d'un joueur, vous avez la méthode [Player].hasPermissions(String perm).
Code:
Player p = e.getPlayer();
if (p.hasPermission("igates.use"))
{
// Faisons ce qu'il faut faire ! :D
}
Notez qu'une autre méthode, utilisant cette fois une instance de la classe Permission, permet de vérifier une permission. Ce système permet enfaite de définir vos permissions dans le fichier plugin.yml. Mais celle-ci est laborieuse et nécessiterait d'expliquer plusieurs grand défauts, et comment les combler.

Erreurs fréquentes :

Grid_Lava_Bucket.png
Utiliser des références aux objets Player :

Imaginons un cas très précis, vous voulez que votre plugin ajoute quelqu'un à une ArrayList quand il casse un bloc, et qu'il soit retiré de cette ArrayList quand il en pose un. (Ne me demandez même pas l'utilité, c'est pas le but. :) ).
Je ne noterai pas comment gérer les évènements, je donnerais juste ça :
Code:
private ArrayList<Player> list = new ArrayList<Player>();
Seulement, si vous essayer de faire le plugin que j'ai fait, vous avez a peu près 80% de chance qu'il ne fonctionne pas et/ou qu'il produisent des erreurs.

Quesqu'un objet Player ?
C'est une entité 3D placé dans le World, le problème, c'est que quand le joueur va mourir, par exemple, le Server va supprimer l'entité morte et en recrée une nouvelle qu'il va placé au point de Spawn.
Mais votre ArrayList, comme elle contenait références vers des objets Player, ces objets vaudront null ! Vous aurez donc des null dans votre ArrayList !

Pour contrer ce problème, vous pourriez utiliser la méthode .getEntityId(), seulement, elle réagit de la même façon que l'objet.

La seule façon de régler ce problème, c'est de stocker le nom des joueurs (En effet, celui-ci est immodifiable par le joueur puisque c'est le nom du compte Minecraft). Ainsi, quand vous voudrez enregistrez quelqu'un dans la liste :
Code:
list.add(player.getName());
Maintenant, imaginons que vous ayez le nom du joueur, et que vous vouliez lui envoyer un message ([Player].sendMessage("Hello !")). Comment faire pour récupérer un objet Player depuis son nom ?
Utilisez la méthode getPlayer(String name) de la classe Server :
Code:
[Server].getPlayer("bobeuuh");
 

luluesmail

Sportif de haut-niveau dans l'art de la sieste
28 Juillet 2011
347
2
125
RE: Dèvelopper des plugins pour Craftbukkit

Impatient d'avoir fini de lire ton tuto ! ! !
 

SmokyBird

Minecraft Saves
6 Juillet 2011
382
7
13
33
RE: Dèvelopper des plugins pour Craftbukkit

Wow. J'ai lu en vitesse, mais je comprends mieux le fonctionnement d'un petit mod comme celui que tu expliques durant tout ton tutoriel.
Chapeau, franchement ! Merci encore pour ce tutoriel, ça pourrai m'être utile un jour !
 

Yannoulu

Sniffeur professionnel
28 Juin 2011
559
29
23
26
127.0.0.1
www.twitter.com
RE: Dèvelopper des plugins pour Craftbukkit

Super tuto !

J'attends la suite avec impatience, surtout la partie ou on apprend comment faire des commandes !
 

Ptibiscuit

Modérateur sucre vanillé
11 Mars 2011
620
25
13
RE: Dèvelopper des plugins pour Craftbukkit

Une nouvelle petite partie pour colorer les messages.
La partie sur les commandes arrivent, mais elle sera un peu plus longue !
 

Smixi

Vétéran autoproclamé et non mérité du forum.
23 Juin 2011
1 753
6
33
RE: Dèvelopper des plugins pour Craftbukkit

GG!
J'était sur que t'allais faire un tuto =)
Sinon, sa marche pour les mods sa ou quoi ?
 

OasiZ_

Mineur des cavernes
11 Avril 2011
1 612
4
33
RE: Dèvelopper des plugins pour Craftbukkit

non, pour les mods y'a un autre tuto sur le site pour les développer avec eclipse :oui:
 

Ptibiscuit

Modérateur sucre vanillé
11 Mars 2011
620
25
13
RE: Dèvelopper des plugins pour Craftbukkit

Tutoriel sur les commandes terminées. Il y en aura surement un 2ème pour présenter la 2ème manière d'en créer, que les développeurs puissent avoir le choix. :)
 
Statut
N'est pas ouverte pour d'autres réponses.