PermissionAPI
-
Sommaire
Introduction
Depuis la 1.11, Forge a rajouté un package nommé net.minecraftforge.server.permission contenant la classe PermissionAPI qui permet désormais de
gérer les permissions avec un système interne à Forge.
Le concept est le suivant: les mods enregistrent des permissions (appelées Nodes) via
PermissionAPI#registerNode puis, lorsque qu’ils ont besoin de vérifier si un joueur a une permission, ils n’ont qu’utiliser la fonction
PermissionAPI#hasPermission.
Pour gérer tout ceci, Forge a besoin d’une classe implémentant l’interface IPermissionHandler, il n’y a qu’une et qu’une seule classe qui peut gérer
les permissions. Forge met à disposition sa propre classe appelée DefaultPermissionHandler, cependant elle n’est pas très complète et c’est, je pense,
voulu de la part des développeurs de Forge. Cette classe peut être changée en utilisant PermissionAPI#setPermissionHandler.Dans ce tutoriel nous aborderons tout d’abord la façon d’enregistrer les nodes et de vérifier si un joueur a une permission, puis nous nous intéresserons
à la façon de créer son propre système.Pré-requis
Il n’y a aucun pré-requis à ce tutoriel.
Code
Enregistrer ses permissions
Pour enregistrer vos permissions, il faut appeler la fonction PermissionAPI#registerNode après la phase de pre-initialisation, c’est très important.
La fonction prend 3 paramètres :- Le nom de la node (String) : c’est le nom de votre permission, elle doit être du format modid.subgroup.permission_id, ce n’est pas obligatoire mais
c’est le format recommandé par Forge. Attention, les nodes sont sensibles à la casse (a != A). - Le niveau de permission par défaut (DefaultPermissionLevel) : cela sert à définir qui a cette permission (par défaut), les valeurs possibles sont ALL, OP, NONE, elles font partie de l’enum DefaultPermissionLevel.
- La description (String) : cet argument vous sert à décrire à quoi sert votre permission.
Attention : aucun de ces arguments ne peut être null.
Exemple d’enregistrement d’une permission fictive :
@EventHandler public void init(FMLInitializationEvent event) { PermissionAPI.registerNode("mfftuto.items.laser", DefaultPermissionLevel.OP, "Donne accès à l'utilisation du pistolet laser"); }
Voilà, c’est tout pour l’enregistrement des permissions.
Vérifier si un joueur a une permission
Une fois vos permissions enregistrées, vous pouvez à tout moment appeler la fonction PermissionAPI#hasPermission pour savoir si le joueur passé en
argument a la permission donnée.La fonction prend deux arguments :
- Le joueur (EntityPlayer) : le joueur que vous voulez tester.
- La node (String) : la permission à tester.
Exemple fictif :
public ActionResult <itemstack>onItemRightClick(World world, EntityPlayer player, EnumHand hand) { if(PermissionAPI.hasPermission(player, "mfftuto.items.laser")) { // On envoie un rayon laser // ... return new ActionResult(EnumActionResult.SUCCESS, player.getHeldItem(hand)); } return new ActionResult(EnumActionResult.PASS, player.getHeldItem(hand)); }
On peut aussi utiliser un autre prototype de la fonction :
public static boolean hasPermission(GameProfile profile, String node, @Nullable IContext context)
L’instance du GameProfile peut-être récupérée depuis l’instance du joueur avec :
player.getGameProfile();
La node est votre permission.
Le IContext est un context dans lequel se trouve le joueur, il en existe plusieurs créés par Forge :
- AreaContext
- BlockPosContext
- PlayerContext
- TargetContext
- WorldContext
Je ne parlerai pas des ContextKey car je n’ai pas encore totalement assimilé le fonctionnement.
Cet argument sera passé à la classe implémentant l’interface IPermissionHandler afin qu’il puisse l’utiliser pour savoir si le joueur possède la permission donnée.
Exemple :
public ActionResult <itemstack>onItemRightClick(World world, EntityPlayer player, EnumHand hand) { if(PermissionAPI.hasPermission(player, "mfftuto.items.laser", new WorldContext(world))) { // On envoie un rayon laser // ... return new ActionResult(EnumActionResult.SUCCESS, player.getHeldItem(hand)); } return new ActionResult(EnumActionResult.PASS, player.getHeldItem(hand)); }
Les contexts ne sont pas utilisés par la classe DefaultPermissionHandler de Forge mais, comme dit dans l’introduction, je ne pense pas que cette API soit
faite pour que l’on garde la classe de base. Deuxième information, la fonction PermissionAPI#hasPermission(EntityPlayer player, String node) crée un PlayerContext.Créer sa propre implémentation de IPermissionHandle
L’interface IPermissionHandler vous permet de créer votre propre système pour gérer les permissions.
Premièrement il vous faut créer une classe implémentant cette interface :public class CustomPermissionHandler implements IPermissionHandler { @Override public void registerNode(String node, DefaultPermissionLevel level, String desc) { } @Override public Collection <string>getRegisteredNodes() { return null; } @Override public boolean hasPermission(GameProfile profile, String node, IContext context) { return false; } @Override public String getNodeDescription(String node) { return null; } }
Dans cette classe, la fonction registerNode sera appelée à chaque fois qu’un mod va enregistrer une permission.
La fonction getRegisteredNodes doit renvoyer toutes les permissions enregistrées.
La fonction hasPermission doit renvoyer si oui ou non le joueur a la permission donnée.
Et la fonction getNodeDescription doit renvoyer la description de la permission donnée.Je ne vais pas vous faire d’exemple ici, vous pouvez regarder comment gère tout ceci Forge dans la classe DefaultPermissionHandler mais
le but ici est de faire votre propre système.Il vous faudra ensuite définir votre classe comme PermissionHandler durant la phase de pre-initialisation :
@EventHandler public void preInit(FMLPreInitializationEvent event) { PermissionAPI.setPermissionHandler(new CustomPermissionHandler()); }
Et c’est tout. Merci d’avoir lu, mettez un pouce bleu et n’hésitez pas à partager :troll:
- Le nom de la node (String) : c’est le nom de votre permission, elle doit être du format modid.subgroup.permission_id, ce n’est pas obligatoire mais
-
Bravo BRAVO !
-
Salut,
Premièrement super tuto ! Mais une chose reste floue pour moi, à quoi servent les autres IContext que tu énumères, AreaContext, BlockPosContext, PlayerContext, TargetContext ?
Quand est-ce qu’il est indispensable de s’en servir ? Car ton exemple ne nous illustre que le WorldContext. -
Merci, d’après ce que j’ai compris ils permettent de définir le contexte dans lequel le joueur se trouve. Par exemple, le joueur peut-il utiliser l’arme laser quand il est dans telle ou telle zone ?
PermissionAPI.hasPermission(player.getGameProfile(), "mfftuto.item.laser", new AreaContext(player, new AxisAlignedBB(0, 0, 0, 10, 10, 10));
Mais comme Forge ne l’utilise pas de base je ne sais pas trop, le mieux reste d’utiliser :
PermissionAPI.hasPermission(player, "mfftuto.item.laser");
Tient si ça t’intéresse : https://github.com/MinecraftForge/MinecraftForge/pull/3155
EDIT : Après avoir fait quelques recherches, je peux définir correctement à quoi servent les contextes. Ils permettent au PermissionHandler d’avoir des précisions sur le joueur.
Exemples :
Le joueur peut-il casser un bloc ?
-> Il est dans l’overworld : ok
-> Il est dans le nether : non
Pour différencier ceci : WorldContextLe joueur peut-il attaquer ?
-> La cible est un mouton : oui
-> La cible n’est pas un mouton : non
Pour différencier : TargetContextLe joueur peut-il se téléporter ?
-> Il est dans la zone de téléportation : oui
-> Il n’est pas dans la zone de téléportation : non
Pour différencier : AreaContextLe joueur casser ce bloc ?
-> Le bloc se trouve en 0,0,0, c’est de la terre et il le casse par en dessous : oui
-> Sinon : non
Pour différencier : BlockPosContextMais encore une fois avec PermissionAPI#hasPermission(EntityPlayer player, String node), c’est sûrement le mieux car on crée un PlayerContext qui contient le monde du joueur, sa position, sa cible, etc …
-
D’accord j’ai compris, merci de toutes ces informations qui en aideront plus d’un !
-
-
-