IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Vous êtes nouveau sur Developpez.com ? Créez votre compte ou connectez-vous afin de pouvoir participer !

Vous devez avoir un compte Developpez.com et être connecté pour pouvoir participer aux discussions.

Vous n'avez pas encore de compte Developpez.com ? Créez-en un en quelques instants, c'est entièrement gratuit !

Si vous disposez déjà d'un compte et qu'il est bien activé, connectez-vous à l'aide du formulaire ci-dessous.

Identifiez-vous
Identifiant
Mot de passe
Mot de passe oublié ?
Créer un compte

L'inscription est gratuite et ne vous prendra que quelques instants !

Je m'inscris !

Utiliser la JSR 353 pour accéder à la Web API de Guild Wars 2 - partie 4
Par bouye

Le , par bouye

0PARTAGES

Suite à mon dernier post, j'avais prévu de commencer à implémenter quelque chose permettant de visualiser la carte du jeu (soit en JavaScript via Leaflet, soit de me casser la tête pour le faire directement en JavaFX) mais il se trouve qu'ArenaNet a fini par mettre au point la procédure d'authentification qui permet d’accéder aux informations privées des comptes. La première mouture cette authentification était basée sur un système de sécurité inspiré de OAuth 2.0. Cependant, cette méthode d'accès a vite été dépréciée, de manière à éviter des trous et failles de sécurité connus sur cette architecture. En replacement, ArenaNet a mis en place un système de jeton de sécurité définis par l'utilisateur lui-même. Ce nouveau système, outre le fait d'éviter toute la controverse autour de OAuth 2.0, est très très simple à utiliser.

C'est vous, propriétaire du compte, qui allez générer une clé disposant de permissions dans tel ou tel domaine. Vous devez ensuite passer ce jeton dans une application qui pourra alors accéder à vos données privées (ou du moins à une partie, en fonction des permissions accordées). L'application pourra conserver ce jeton (si possible dans un emplacement sécurisé) de manière à pouvoir le réutiliser plus tard. Donc, vous devrez, dans une certaine mesure, faire confiance à l'application pour qu'elle ne distribue pas votre jeton (tout comme vous devez faire confiances aux applications qui stockent ou utilisent vos identifiants ou mots de passe). Cependant, vous pouvez à tout moment résilier cette clé pour interdire de nouveau l’accès à votre compte : l'application ne peut alors plus accéder à vos données avec le jeton qu'elle détient.

Nous allons commencer par accéder à la liste des personnages et, pour les besoins de l'interface graphique, nous allons également accéder à votre compte et aux informations concernant les guides. Pour le moment les informations accessibles sont très basiques et il n'est pas du tout possible de récupérer votre adresse mél, d'effacer un personnage ou de modifier son inventaire ; donc il n'y a aucun soucis à avoir de ce coté là.

Il est inutile de préciser, je pense, que vous ne pourrez pas tester le programme fourni dans cet article si vous n'avez pas de compte de jeu actif (il faut donc avoir acheté Guild Wars 2 ou avoir testé une des périodes d'essai gratuit). Cependant, j'ai tout de même inclus un mode démo présentant un faux compte et de faux personnages et qui peut être utilisé sans compte réel et ni connexion avec le site web de l'API.

JSR 374
Hein, quoi, comment ? Mais c'est la JSR 353 qu'on utilise !

Oui, mais... la JSR 374 concerne le développement de l'API JSON-P 1.1 qui sera bien entendu une évolution de l'API JSON-P 1.0 actuelle et contiendra de nouvelles fonctionnalités (notamment le support de JSON Pointer, JSON Patch et JSON Merge Patch, ainsi qu'une plus grande intégration avec les fonctionnalités du JDK8). Bien qu'elle ne soit pas encore d’actualité ni complètement spécifiée, cela vaut le coup de conserver un œil sur le site des JCP pour se tenir au courant de son évolution et de sa future disponibilité.


Il est possible participer au développement de la JSR 374. Vous pouvez également montrer votre soutient à cette JSR via le programme Adopt-a-JSR (adoptez une JSR).

Charabia légal
Guild Wars et Guild Wars 2 sont des marques déposées de ArenaNet et NCsoft. De plus, toutes les images restent la propriété de ArenaNet. De même, la Web API utilisée reste la propriété de ArenaNet qui peut décider de la retirer ou d'en interdire l'utilisation comme bon lui semble. Et bien sûr, je ne suis affilié ni avec ArenaNet, ni avec NCsoft.

Création du jeton de sécurité
Ouvrez votre navigateur sur le site officiel du jeu (https://www.guildwars2.com/fr/) ou un de ses sites parents (forums officiels, support technique). Sur le coté droit de l’écran, cliquez sur Connectez-vous (sur le site principal) ou S'identifier (sur les forums). Saisissez maintenant les identifiants avec lesquels vous vous connectez en jeu, puis cliquez sur Connexion. Si vous utilisez l'autentificateur mobile et si c'est la première fois que vous vous connectez depuis votre emplacement actuel, vous serez probablement amenez à saisir un code de sécurité généré depuis votre téléphone ou tablette.


Déplacez vous dans la gestion de votre compte en cliquant sur Compte en dessous de votre identifiant et de votre adresse mél puis allez dans Clés d'application. Si vous n'avez jamais défini de jeton de sécurité auparavant, cette section devrait être vide. Cliquez maintenant sur Nouvelle clé.


Par défaut, tout jeton de sécurité a accès à certaines informations basiques sur votre compte mais nous avons besoin en plus d’accéder à la liste de vos personnages ; nous allons devoir lui donner un droit d’accès supplémentaire : pensez donc à cocher la case characters. Pour le moment nous n'avons pas besoin de la permission tradingpost qui permet d'accéder aux transaction effectuées sur le comptoir de vente donc vous pouvez la laisser désactivée si vous préférez. Enfin, donnez un nom à votre jeton (par exemple : Jeton de test) et cliquez sur Créer une clé d'application.


Votre compte dispose maintenant d'un jeton que vous pouvez saisir dans une application. Ce jeton se présente sous la forme d'une très très longue chaîne alphanumérique de style XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXXXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX. Avec ce jeton, une application peut s'interfacer avec votre compte et peut en retirer des informations. Depuis quelques jours, il est également possible d'obtenir un QR code en cliquant sur le bouton le plus à droite de la clé. Cela vous permettra donc d'utiliser les fonctions existantes de votre plateforme ou de votre logiciel pour scanner l'image de ce code plutôt que de devoir ressaisir la clé à la main. Pour les besoin de ce test, nous allons rester simple et il faudra saisir la clé manuellement. Bien qu'il soit possible de modifier le nom de la clé en cliquant sur Modifier, il est impossible de changer les permissions ; donc si, après coup, vous avez besoin d'une clé disposant de permissions différentes, il vous suffit d'en créer une nouvelle.

Bien que vous allez être amenés à fournir publiquement cette clé dans des applications tierces auxquelles vous accorderez votre confiance, évitez quand même de la rendre publique sur des sites web ou de la distribuer n'importe où et à n'importe qui et ce pour des raisons de sécurité. Actuellement, l'API ne permet pas de faire de modifications sur un compte mais, dans le futur, il sera peut-être possible de participer aux enchères ou encore de gérer les inventaires de votre personnage, votre coffre de compte ou de guilde. Il serait stupide que quelqu'un puisse accéder à votre compte et le dépouiller de son contenu depuis une application tierce.

Vous pouvez, à tout moment, désactiver un jeton de sécurité en retournant dans l'interface d'administration de votre compte et en le supprimant en cliquant sur Supprimer, ce qui empêchera tout accès ultérieur à votre compte par cette clé.

Contexte
Généralement dans les jeux de ce type, chaque personnage a une seule guilde qui lui est propre. Guild Wars 1 avait géré la chose différemment en faisant que la guilde soit en fait une propriété du compte ; ainsi tous les personnages d'un compte faisaient automatiquement partie de la même guilde (et donc de la même alliance de guilde). Mais cela n’était pas au gout de tout le monde : certains joueurs préfèrent en effet avoir des moment d'anonymat sans pour autant être déclarés en mode "hors-ligne". D'autres encore considèrent tout simplement leurs personnages comme des "personnes" différentes et distinctes sans rapport direct les uns d'avec les autres et donc préfèrent avoir des contacts différents et des guildes différentes et distinctes pour chaque personnage.

Guild Wars 2 a essayé de ménager la chèvre et le chou en faisant qu'un compte dispose au maximum de 5 guildes différentes, et que chaque personnage peut représenter (c'est à dire faire partie) une seule guilde active à la fois, et ce indépendamment des autres personnages. Il est également possible de faire qu'un personnage ne représente aucune guilde.

En détails
À partir de maintenant, pour accéder aux données nécessitant une authentification, il va falloir envoyer le jeton de sécurité dans l'URL permettant d'interroger le point d’accès en utilisant le paramètre access_token de manière similaire à la syntaxe <url du point d'entree>?access_token=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXXXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX. Bien qu'il soit tout à fait possible d'utiliser cette URL directement dans votre navigateur web pour vos tests de tentative d’accès comme nous l'avons fait précédemment, je vous déconseille de le faire. En effet, ce faisant, votre clé d'application restera visible dans votre historique de navigation, ce qui peut la rendre accessible à autrui. Donc pensez à purger votre historique de navigation ou à résilier la clé utilisée une fois vos test accomplis.

Nous allons récupérer la liste des personnage de votre compte. Les informations définies dans un personnage contiennent : son nom, sa profession, sa race, son niveau et la guilde qu'il représente. Certaines informations semblent être optionnelles : par exemple, lorsque j'ai fait mes premiers tests, nous étions en pleine période de bêta-test fermé de l'extension Heart of Thorns et donc j'avais un personnage de profession Revenant (profession rajoutée dans l'addon) qui était listé comme sans profession. On peut supposer qu'il en sera de même, le jour ou une extension ajoutera une nouvelle race. De plus, il est possible pour un personnage de ne pas représenter de guilde du tout, nous devons donc nous préparer à gérer des données vides ou absentes.

Pour accéder à la liste de vos personnages, vous devez accéder à l'endpoint characters disponible à l'URL https://api.guildwars2.com/v2/characters. Ainsi, une requête sur https://api.guildwars2.com/v2/characters?access_token=<jeton de sécurité> renverra un tableau JSON listant les noms de tous les personnages de votre compte.

Code JSON : Sélectionner tout
 [ "Logan Thackeray", "Eir Stegalkin"]

Il est possible ensuite de récupérer les informations sur un ou plusieurs personnages en construisant une URL contenant le nom du personnage ou encore en utilisant les paramètres id ou ids habituels (ici les identifiants sont les noms des personnages). D’après mes test, ce point d’entrée ne supporte pas cependant le paramètre ids=all, probablement pour raisons de sécurité ; il faut donc fournir une liste de noms à chaque fois. À noter également qu'il est tout le temps nécessaire de spécifier le jeton de sécurité sous peine d’échec de la requête. Par exemple :

  • https://api.guildwars2.com/v2/characters/<nom du personnage>?access_token=<jeton de sécurité> - Renvoie un objet JSON contenant les informations du personnage spécifié ;
  • https://api.guildwars2.com/v2/characters?id=<nom du personnage>&access_token=<jeton de sécurité> - même chose ;
  • https://api.guildwars2.com/v2/characters?ids=<nom du personnage 1>,<nom du personnage 2>,...,<nom du personnage N>&access_token=<jeton de sécurité> - Renvoie un tableau JSON contenant les informations des personnages spécifiés.


Lors de mes tests, un autre soucis majeur est apparu : il est possible d'utiliser des espaces et des diacritiques (caractères accentués, cédilles, etc. ) dans les noms des personnages ce qui pose des problème sur les URLs construites lors de leur utilisation dans l'API Java. Ainsi, il faudra remplacer les ' ' (espace) par des %20 ou les 'À' par des %C3%80 sous peine d'erreurs diverses lors des ouvertures de flux. Vous pouvez trouver une table de référence des diacritiques sur HTML URL Encoding Reference mais, de toute manière, l'API Java offre des méthodes permettant de remplacer ces caractères par la chaîne appropriée.

PS : une demande a été postée sur le forum pour que chaque personnage soit associé à une id, comme c'est le cas pour la plupart des autres valeurs retournées par la Web API, donc il est possible que dans le futur on puisse éviter de devoir utiliser les noms des personnages pour les requêtes. De plus, des demandes ont été faites pour que d'autres données telles que l'âge du personnage ou encore les tâches quotidiennes effectuées (ex : chemin de donjon) soient rajoutées dans l'objet obtenu. Cette partie de l'API est donc amenée à encore évoluer.

Suivant votre requête, un ou plusieurs objets JSON similaires à l'objet suivant vous seront retournés (oui, je sais que Logan n'est pas un Charr, mais c'est l'exemple de test montré sur le wiki et sur les forums) :

Code JSON : Sélectionner tout
1
2
3
4
5
6
7
8
{ 
    "name": "Logan Thackeray", 
    "race": "Charr", 
    "gender": "Male", 
    "profession": "Guardian", 
    "level": 80, 
    "guild": "4BBB52AA-D768-4FC6-8EDE-C299F2822F0F" 
}

Ici, les champs race, gender et profession ne sont pas des valeurs internationalisables ; il s'agit de valeur d'enums.

Nous allons accéder au compte pour récupérer le nom du compte : une chaîne de texte unique qui identifie un compte et est distincte que l’adresse mél qui sert à vous connecter. Ce n'est pas une donnée privée car il s'agit tout simplement de l'ID utilisateur publiquement visible quand vous postez sur les forums officiels. Elle apparaît également quand vous vous connectez sur la gestion de votre compte ou, en jeu, sur l’écran de sélection des personnages. Nous allons également récupérer, la liste totales des guildes du compte ; j'ai en effet choisi de ne pas charger la guilde pour chaque personnage mais de charger directement les informations de toutes les guildes du compte. De toute manière un personnage ne peut pas représenter une guilde qui ne soit incluse dans le compte.

Pour accéder aux données de votre compte, vous devez accéder à l'endpoint account disponible à l'URL https://api.guildwars2.com/v2/account. Ainsi, une requête sur https://api.guildwars2.com/v2/account?access_token=<jeton de sécurité> renverra un objet JSON contenant votre identificateur, votre nom de compte, l'identificateur du monde auquel est affilié votre compte de même que les guildes auxquelles votre compte est affilié.

Code JSON : Sélectionner tout
1
2
3
4
5
6
 { 
    "id": "b8169418-1c11-405f-91bb-e2b29d602b8a", 
    "name": "ExampleAccount.1234", 
    "world": 1007 
    "guilds": ["75FD83CF-0C45-4834-BC4C-097F93A487AF"] 
 }

Étant donné que, et le compte, et le personnage se réfèrent tous deux aux guildes par un identifiant, il va nous falloir accéder à un troisième endpoint, celui des guildes ce qui nous permettra de récupérer le nom de la guilde ainsi que son tag (une chaine de 2-3 lettres permettant d'identifier rapidement la guilde en jeu). Ce point d’entrée ne nécessite aucune authentification mais utilise encore le format V1 de l'API, donc la syntaxe de la requête ainsi que le format des champs retirées dans l'objet JSON sont légèrement différents de ceux que nous avons manipulés jusqu’à présent (qui sont tous au format V2). De plus, la V1 de l'API ne permet pas de récupérer plusieurs objets par requête ; donc, ici, nous seront obligés de faire entre 0 et 5 requêtes maximales supplémentaires pour accéder à l’intégralité des détails de toutes les guildes du compte.

Pour accéder aux données des guildes, vous devez utiliser l'endpoint guild_details en interrogeant l'URL https://api.guildwars2.com/v1/guild_details.json. Ce point d’accès ne requiert pas d’authentification donc il n'est pas nécessaire de fournir le jeton de sécurité. Il est possible de fournir deux paramètres distincts pour récupérer des informations sur ce point d’entrées :
  • https://api.guildwars2.com/v1/guild_details.json?guild_id=<id de la guilde> - Charge les détails de la guilde en se basant sur son identifiant.
  • https://api.guildwars2.com/v1/guild_details.json?guild_name=<nom de la guilde> - Charge les détails de la guilde en se basant sur son nom.

Dans le cas où les deux paramètres sont spécifiés, c'est guild_id qui prend la précédence. Faites attention lors de l'utilisation du paramètre guild_name, en cas de présence de diacritiques dans le nom de la guilde. Il faudra penser à les échapper tout comme avec le nom du personnage.

L'objet guilde obtenu permet de récupérer également des informations concernant son logo (les identificateurs des images utilisées, les transformations et couleurs) mais il n'existe pas actuellement de source pour générer ou récupérer les logos sur la web API officielle. Donc si vous désirez afficher le logo d'une guilde, il faudra utiliser un pack d'images fourni par un joueur en attendant un futur support de cette fonctionnalité. Ici aussi les flags qui controlent l'orientation des couches d'images qui composent le logo d'une guilde sont des valeurs d'enum.

Voici, par exemple, l'objet définissant la guilde ArenaNet auxquels tous les modérateurs, GM (Game Masters ou maitres du jeu) et employés d'ArenaNet en jeu appartiennent.

Code JSON : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
{ 
    "guild_id":"4BBB52AA-D768-4FC6-8EDE-C299F2822F0F", 
    "guild_name":"ArenaNet", 
    "tag":"ArenaNet", 
    "emblem":{ 
            "background_id":2, 
            "foreground_id":40, 
            "flags":["FlipBackgroundHorizontal","FlipBackgroundVertical"], 
            "background_color_id":473, 
            "foreground_primary_color_id":673, 
            "foreground_secondary_color_id":71 
    } 
}

Enfin, les informations que nous allons récupérer ne sont pas statiques et elles peuvent changer avec le temps : création et suppression de personnage, changement de sexe ou du nom d'un personnage (ce sont des services payants mais tout-à-fait possibles), changement dans la représentation des guilde, quitter ou intégrer une guilde, changer le logo d'une guilde et ses couleurs, etc. Nous allons donc devoir régulièrement mettre à jour nos données affichées. Pour cela, au lieu du Service habituel, nous utiliserons un ScheduledService qui permet d'effectuer une tache récurrente. Il est mentionné plusieurs fois sur les forums officiels que le taux de rétention (c'est à dire la fréquence des mises jours des infos) sur le site de la web API est de 5 minutes ; il est donc inutile de faire une application avec un taux de rafraichissement plus court que ce délai : les données reçues seraient strictement identiques pendant 5 minutes.

Alors que je m'apprêtais à publier ce post, je suis allé faire un tour sur le forum officiel et me suis rendu compte qu'ils venaient de rajouter un nouveau point d'entée, tokeninfo qui permet de tester les permissions d'une clé d'application. J'ai donc modifié mon programme pour inclure cette nouvelle fonctionnalité de manière à effectuer un test sur les permissions avant de lancer la récupération des données du compte, des personnages et des guildes.

Donc si vous accédez à l'URL https://api.guildwars2.com/v2/tokeninfo en spécifiant votre jeton de sécurité dans le paramètre access_token, bien sûr, cela retournera un objet JSON similaire à :

Code JSON : Sélectionner tout
1
2
3
4
5
6
7
8
{ 
    "id": "017A2B0C-A6C5-CC4D-A055-680F427CE8FD", 
    "name": "Jeton de test", 
    "permissions": [ 
        "account", 
        "characters" 
    ] 
}

On peut voir ici que cet objet retourne le nom de la clé définie dans l'interface de création ainsi qu'un tableau JSON contenant toutes les permissions sur cette clé. Certaines informations comme l'id et le nom de la clé sont conservés 5 minutes cotés serveur mais les permissions, quant à elles, sont mises à jour immédiatement (si vous résiliez une clé, un appel à l'API dans les secondes qui suivent indiquera que la clé n'a plus la permission d'accéder à quoi que ce soit ; au bout de 5 minutes la clé sera considérée comme non-existante et une erreur JSON devrait être renvoyée).

En tenant compte du nouvel endpoint permettant de tester le clé, on peut envisager notre programme comme suit :

L'utilisateur saisit sa clé.
  • Tant que la clé saisie n'est pas valide (au niveau de son format, ce qui est facile à vérifier coté client), on ne fait rien.
  • Lorsque le format de la clé est valide, on fait une requête pour récupérer les informations sur cette clé :
    • Si la clé ne dispose pas des permissions appropriées, on affiche une erreur et on ne fait rien.
    • Si la clé dispose des permissions appropriées, on lance un service récurrent qui s'exécute toutes les 5 minutes :
      1. On fait une requête pour récupérer les informations du compte (utile pour la liste de guilde).
      2. Pour chacune des guildes (puisqu'on ne peut pas faire de requête groupée dans l'API V1) :
        • On fait une requête pour récupérer les informations de cette guilde.
      3. On fait une requête pour récupérer la liste de tous les personnages du compte.
      4. On fait une requête pour récupérer les informations de tous les personnages.
      5. On affiche toutes ces informations dans l'interface graphique.




Cooodage

Nous allons commencer par rajouter quelques nouvelles méthodes dans notre classe utilitaire QueryUtils.

Code Java : Sélectionner tout
1
2
3
4
5
public static String encodeURLParameter(final String value) throws UnsupportedEncodingException { 
    String result = URLEncoder.encode(value, "utf-8"); // NOI18N. 
    result = result.replaceAll("\\+", "%20"); // NOI18N. 
    return result; 
}

Cette première méthode permet d'encoder correctement les paramètres passés à une requête pour en supprimer les espaces et les diacritiques. La classe java.net.URLEncoder permet d’échapper les diacritiques mais remplace le caractère ' ' (espace) par un '+' (signe plus) ; donc il nous faut replacer ce symbole par la chaîne "%20". Et comme '+' est un caractère spécial dans les patterns, il nous faut bien sur l’échapper avec "\\" lorsqu'on invoque la méthode replaceAll().

J'ai ensuite défini quelques méthodes de conversion de tableaux en listes :

Code Java : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public static <T> List<T> jsonStringArrayToList(final JsonArray array, final Function<String, T> converter) { 
    return jsonArrayToList(array, JsonString.class, jsonString -> { 
        final String string = jsonString.getString(); 
        return converter.apply(string); 
    }); 
} 
  
public static <T> List<T> jsonObjectArrayToList(final JsonArray array, final Function<JsonObject, T> converter) { 
    return jsonArrayToList(array, JsonObject.class, converter); 
} 
  
public static <T> List<T> jsonArrayArrayToList(final JsonArray array, final Function<JsonArray, T> converter) { 
    return jsonArrayToList(array, JsonArray.class, converter); 
}

Ce trio de méthodes permet de convertir un tableau JSON d’entités de type S (S doit être une classe héritant de la classe JsonValue) en une liste Java d'objets de type T. Ici, je vais les utiliser lorsque je récupère plusieurs personnages en même temps, pour les guildes d'un compte et pour les flags du logo d'une guildes. Elles me seront encore plus utiles la prochaine fois lorsque j'aurais un grand nombre de valeurs à manipuler en retirant les historiques de vente. Ces trois méthodes en invoquent une 4ème plus générique, ce qui permet d’éviter pas mal de duplication de code :

Code Java : Sélectionner tout
1
2
3
4
5
6
7
public static <S extends JsonValue, T> List<T> jsonArrayToList(final JsonArray array, final Class<S> sourceClass, final Function<S, T> converter) { 
    final List<T> result = array.getValuesAs(sourceClass) 
            .stream() 
            .map(converter) 
            .collect(Collectors.toList()); 
    return Collections.unmodifiableList(result); 
}

Par exemple, pour instancier les personnages, dans la classe CharactersQuery chargée d'interroger le point d’accès, nous pouvons faire :

Code Java : Sélectionner tout
1
2
3
4
5
6
7
8
9
public static List<Character> characterInfos(final String applicationKey, final String... names) throws IOException, IllegalArgumentException { 
    final boolean applicationKeyValid = ApplicationKeyUtils.validateApplicationKey(applicationKey); 
    if (!applicationKeyValid) { 
        throw new IllegalArgumentException(); 
    } 
    final String url = String.format("%s?ids=%s&access_token=%s", BASECODE, QueryUtils.encodeURLParameter(QueryUtils.idsToString(names)), applicationKey); // NOI18N. 
    final JsonArray jsonArray = QueryUtils.queryArray(url); 
    return QueryUtils.jsonObjectArrayToList(jsonArray, CharacterFactory::createCharacter); 
}

Ici, la méthode createCharacter() dans la classe CharacterFactory, la fabrique, est chargée d'instancier chaque personnage à partir d'un objet JSON contenu dans le tableau récupéré.

Compte tenu du fait que de nouvelles valeurs d'enum peuvent être ajoutées avec le temps (ex : lorsque l'extension sera disponible et une fois l'API mise à jour, une valeur Revenant sera contenue dans le champs profession d'un personnage mais pour le moment ces personnages n'ont pas de profession), je vais utiliser une approche un peu plus précautionneuse. Dans chaque enum que je vais définir, je vais désormais inclure une valeur UNKNOWN (inconnu) qui permettra d'indiquer que la valeur récupérée par la requête est soit null soit nouvelle (ajoutée ultérieurement).

Prenons par exemple l'enum qui définit la profession :

Code Java : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public enum Profession { 
  
    ELEMENTALIST("Elementalist"), // NOI18N. 
    ENGINEER("Engineer"), // NOI18N. 
    GUARDIAN("Guardian"), // NOI18N. 
    MESMER("Mesmer"), // NOI18N. 
    NECROMANCER("Necromancer"), // NOI18N. 
    RANGER("Ranger"), // NOI18N. 
    REVENANT("Revenant"), // NOI18N. 
    THIEF("Thief"), // NOI18N. 
    WARRIOR("Warrior"), // NOI18N. 
    UNKNOWN(null); 
  
    private final String value; 
  
    Profession(final String value) { 
        this.value = value; 
    } 
  
    public static Profession find(final String value) { 
        Profession result = Profession.UNKNOWN; 
        if (value != null) { 
            for (final Profession toTest : values()) { 
                if (value.equals(toTest.value)) { 
                    result = toTest; 
                    break; 
                } 
            } 
        } 
        return result; 
    } 
}

Désormais, si un personnage n'a pas de profession ou une nouvelle profession inconnue coté client, nous utiliserons la valeur Profession.UNKNOWN. Nous ferons quelque chose de similaires pour toutes les autres valeurs d'enum (race, etc.) que nous allons être amenées à manipuler.

Il nous faut également tenir compte du fait que certains champs peuvent être omis dans l'objet JSON reçu. Par exemple, lorsque je recevais le descriptif de mon personnage Revenant, le champ profession était tout simplement absent du JSON. Tenter d’accéder à ce champs absent levait une NullPointerException ; désormais, nous allons donc tester si le champ est présent avant d'y accéder. Ainsi, dans la fabrique chargée de créer les personnages, nous avons :

Code Java : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
public static Character createCharacter(final JsonObject jsonObject) { 
    final Character result = new Character(); 
    [....] 
    result.race = jsonObject.containsKey("race") ? Character.Race.find(jsonObject.getString("race")) : Character.Race.UNKNOWN; // NOI18N. 
    result.profession = jsonObject.containsKey("profession") ? Character.Profession.find(jsonObject.getString("profession")) : Character.Profession.UNKNOWN; // NOI18N. 
    [...] 
    result.guild = jsonObject.containsKey("guild") ? jsonObject.getString("guild") : null; // NOI18N. 
    [...] 
    return result; 
}

Ici, la classe Character fait référence à test.data.character.Character et non pas à java.lang.Character.

Maintenant que vous avez cela; le codage de l'objet TokenInfo ainsi que de l'enum définissant les permissions, de la fabrique et de l'objet requête associés est assez trivial. Il vous suffit donc de vous référer au code source.

Ceux qui sont intéressés par le code UI devraient également aller voir du coté du prédicat servant à filtrer la liste de personnages pour savoir comment sont gérés et configurés les divers critères de filtrage en fonction du nom du personnage, de son sexe, de sa race, de sa profession, etc. Idem pour l'utilisation d'une cellule customisée qui permet un affichage plus joli. Malheureusement l'API actuelle ne permet pas de récupérer les portraits des personnages pour le moment donc le cadre restera vide. Il peut être également intéressant de jeter un coup d’œil au code qui permet d'afficher le genre correct de la profession et de la race en fonction du sexe du personnage, chose qui n'est pas apparent en anglais mais plutôt utile en français (ex : en mode démo, Eir est marquée comme étant une Rôdeuse Norne et non pas un Rôdeur Norn)

À noter que pour ce que j'en ai vu, les jetons de sécurité sont principalement composés de caractères [0-9A-F]. Vous verrez dans le code source la classe test.text.ApplicationKeyTextFormatter, l'objet permettant de filtrer le champ d’édition, supporte également le symbole X que j'ai rajouté pour permettre la saisie de la clé de démo. Si jamais votre clé se compose de symboles autres, vous devez modifier cette classe, de même que la classe test.text.ApplicationKeyUtils. Pensez également à me le signaler en commentaire, que je puisse mettre à jour le code source sur GitHub.

Au final
Au lancement du programme, rien ne sera affiché ; vous devrez saisir votre jeton de sécurité dans le champ textuel approprié. Lorsque le programme détecte que la clé a un format valide, il lancera la récupération des permissions de la clé et, et en cas de permissions suffisantes, le service de mise à jour automatique. Si vous voulez tester le programme en mode démo, il vous suffit d'utiliser la clé XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXXXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX au lieu d'un clé de sécurité normale. Dans ce cas, le programme ira chercher des données JSON pré-générées contenues dans le package test.demo ; aucun accès ne sera fait sur le site de la web API du jeu ou à un quelconque compte de jeu.

Si vous ne voulez pas passer votre temps à coller ou retaper votre jeton d’accès dans le champ de saisi, vous pouvez également créer un fichier nommé settings.properties sur la racine du projet et y déclarer une valeur app.key contenant votre clé d'application. Évidement, il ne s'agit pas là d'un emplacement ou d'un stockage sécurisé, donc utilisez le avec parcimonie. Par exemple, avec la clé de démo :

Code Properties : Sélectionner tout
app.key=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXXXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX

Lorsque le contrôleur est chargé, ce fichier, s'il existe, sera lu et la valeur de clé sera recopiée dans le champs de saisie ce qui lancement automatiquement un accès à vos données.

Dans tous les cas, si la clé d'application est valide ou si vous utilisez la clé de démo, vous devriez obtenir un affichage similaire à :


Code source
... comme j'ai atteins mon quota de 5 fichiers max par message, je ne vous met pas d'archive cette fois-ci...
La version la plus récente du projet, au format NetBeans, est accessible sur GitHub.

Une erreur dans cette actualité ? Signalez-nous-la !