Page 1 sur 2

Journal d'un développeur Java - Le code obfusqué

Publié : 07 oct. 2015, 00:20
par ORelio
Imagefactions-trollface-simplifie-fkin-kidding-me.png

Journal d'un développeur Java
Un jour dans la peau d'un créateur de mods pour Minecraft

Edition Spéciale - Le cauchemar du modding java sur code obfusqué

Bonjour à tous et merci d'être venus nombreux à cette conférence sur le modding Minecraft.
Bien que je l'ai déjà dit ingame je le redis ici sur le forum - la dernière version du launcher est spéciale.
En effet il s'agit de la première version du launcher réalisée sans utliser le Minecraft Coder Pack.

Comme vous le savez, il était de plus en plus dur pour moi d'intégrer les mods du launcher au fur et à mesure des versions de Minecraft.
La raison ? Les délais de plus en plus long pour la sortie du MinecraftCoder Pack, et son incapacité croissante à gérer des versions un peu moddées du jeu,
pour que je puissse rendre mes mods compatibles avec Optifine. Il s'en découlait alors des versions simplifiées, sans capes et Shaders :/
A l'heure où j'écris ces lignes, le Minecraft Coder Pack en est encore à la version 1.8.0 du jeu, qui est vieille de plus d'un an... (1.8.8 à ce jour)

Mais qu'est-ce que ce fameux MCP dont tous les moddeurs parlent ?
Il s'agit d'un kit qui permet de réaliser facilement des mods pour Minecraft :
- Décompilation automatique du code du jeu
- Correction automatique de toutes les erreurs de compilation
- Renommage automatique de tout le code avec des noms de variables clairs et de la documentation
En gros il vous permet d'avoir sous les yeux le code source du jeu presque comme le verrait un employé de Mojang.
Il vous suffit alors de faire vos modifications, et vous pouvez tester ou exporter votre mod le tout en un clic.
En vrai, le code du jeu est obfusqué et illisible, comme ceci par exemple après simple décompilation :

Code : Tout sélectionner

//Une classe prise au hasard dans Minecraft 1.8.8 public class ahu extends afh { public static final amm<ahu.a> a = amm.a("facing", ahu.a.class); public static final amk b = amk.a("powered"); // [...] public alz a(adm ☃, cj ☃, cq ☃, float ☃, float ☃, float ☃, int ☃, pr ☃) { alz ☃ = Q().a(b, Boolean.valueOf(false)); if (a(☃, ☃, ☃.d())) { return ☃.a(a, ahu.a.a(☃, ☃.aP())); } for (cq ☃ : cq.c.a) { if ((☃ != ☃) && (a(☃, ☃, ☃.d()))) { return ☃.a(a, ahu.a.a(☃, ☃.aP())); } } if (adm.a(☃, ☃.b())) { return ☃.a(a, ahu.a.a(cq.b, ☃.aP())); } return ☃; }
Comme vous pouvez le voir, c'est complètement illisible. Pour faire un mod sans le Coder Pack, il faut :
- Décompiler le jeu : Ça encore ça va, c'est pas trop dur, il suffit de lancer la décompilation et d'attendre que ça se fasse ^^
- Retrouver quels sont les fichiers qu'on veut modifier : un peu plus dur, vu que tout dans le code a un nom aléatoire... sauf les chaînes de caractère qui sont alors d'une aide précieuse !
- Faire les modification en adaptant le code et en faisant un travail d'investigation : "alors, du coup, la référence à la classe Minecraft c'est azu ou cj dans cette version ? Ah ouais, ça ... donc ça... ok ! donc ça fait azh.c.d();, logique !"
- Corriger toutes les 142 $ùµ%@#§ erreurs de compilation ! C'est la partie la plus longue et fastidieuse.
- Recompiler, et hop ! On a le mod porté sur la dernière version du jeu.

S'il y a des développeurs dans la salle ... Ah, vous deux, au fond ?
Bon alors, déjà, merci d'être venus, donc, je vais détailler mon erreur préférée qui m'a fait perdre pas mal de cheveux :

Code : Tout sélectionner

// Dans un premier fichier public class abc { public def a; private int b; // [...] public enum a { a, b, c; } } // Et dans un autre fichier public class ghi { private void a(abc.a ☃) { if (☃ == abc.a.a) { // [...] } } }
Alors, l'erreur n'est pas piquée des hannetons donc je vais la détailler :
On a deux classes abc et ghi, je veux modifier ghi, mais ghi ne compile pas. Pourquoi ?
Réponse, tenez vous bien, parce qu'en tentant d'accéder à l'élément a de l'énumération a de abc, le compilateur croit que l'on désigne le champ a : ben oui, ils ont le même nom.
Originellement, ils avaient un nom différent donc ça marchait, mais ensuite l'obfuscateur est passé et les deux se sont retrouvées avec le nom a. Cela marche, mais on ne peut plus le recompiler.
Et non, on ne peut pas les renommer, d'autres parties du code font référence au champ abc.a et à l'énumération abc.a : on est apparemment bloqués.
La solution est proprement immonde, mais c'est la seule que j'ai trouvé pour maintenir la compatibilité avec le reste du code donc sans renommer :

Code : Tout sélectionner

public class abc { public def a; private int b; // [...] public abc.a a_a; public abc.a a_b; public abc.a a_c; public enum a { a, b, c; static { a_a = a; a_b = b; a_c = c; } } } // Et dans un autre fichier public class ghi { private void a(abc.a ☃) { if (☃ == abc.a_a) { // [...] } } }
Afin de ne pas référencer abc.a.a, on ajoute un champ abc.a_a qui doit contenir la valeur équivalente à abc.a.a.
En utilisant l'initialiseur statique dans abc.a, on force l'énumération à référencer d'elle-même le champ a_a sans essayer de référencer a.a
Ensuite on peut utiliser le champ abc.a_a sans que cela soulève d'ambiguïté pour le compilateur, et donc ça compile ! Miracle Image

... Génial non !?

Imagetumbleweed.gif

Mais... Mais... Pourquoi la salle est-elle vide ?
Ah oui, une question d'un survivant, j'écoute ... Ce que je fais dans la vie ?
C'est très simple, le jour je programme, mais quand vient la nuit...

Image

Comment ça, pas drôle ? Hé attendez ! Ne partez pas ! Je ne vous ai pas encore parlé du cauchemar des bonhommes de neige !
C'est quand tous les arguments d'une fonction ont le même nom ! ! Il faut alors retrouver qui va où est c'est super énervant !

... Ah, bon, la salle est maintenant complètement vide. Bon, je crois que c'est l'heure que j'aille dormir.
Bonne nuit feutre, bonne nuit tableau blanc. Merci de m'avoir accompagnés durant cette conférence qui a déchaîné les foules.

Et merci d'avoir lu, si vous en avez eu le courage, cet unique numéro du journal d'un moddeur incompris.
Cette version du launcher m'aura demandé trois jours de dur travail contre trois heures avec le MCP alors je compte sur vous pour en profiter !

C'était ORelio pour HelloMinecraft, à vous les studios !

Re: Journal d'un développeur Java - Le code obfusqué

Publié : 07 oct. 2015, 00:31
par Edrixal
Je commence à peine une formation dans le domaine et je compatis déjà ^^ Perso rien que de lire le code des autres qui on des noms de variables/constante/fonction/procédure qui parfois ne veulent juste rien dire cela devient un vrais calvaire d'arrivée a les aider xD Alors vue le bordel que c'est de ton coter ... Tu a bien du courage ! Et rien que pour ça tu mériterais une médaille ^^

Re: Journal d'un développeur Java - Le code obfusqué

Publié : 07 oct. 2015, 07:50
par GenialJerome
C'est sûr que si les noms de variables et de fonctions ne sont pas explicite, ça va être dur de savoir à quoi elles servent, à part savoir qu'elles sont utiles pour le programme :lol:

Re: Journal d'un développeur Java - Le code obfusqué

Publié : 07 oct. 2015, 08:17
par foufou25
Je vois les memes choses sur mon ordi au debut...mdr

Re: Journal d'un développeur Java - Le code obfusqué

Publié : 07 oct. 2015, 16:27
par ZichaButterfly
Cela me rappelle le temps où je codais aussi :)
Pourquoi nous autres programmeurs sommes nous allergiques aux commentaires. Ils simplifient tellement la vie de celui qui doit reprendre notre code, un jour ou l'autre. (reprendre mon code, jamais, vous n'y pensez pas !) :geek:

Un grand MERCI à toi ORelio, pour tout le travail que tu fais dans l'ombre, et qu'on imagine même pas.

Re: Journal d'un développeur Java - Le code obfusqué

Publié : 07 oct. 2015, 23:05
par ORelio
Merci pour vos commentaires, ça fait plaisir, honnêtement je ne savais pas si beaucoup de personnes pourraient comprendre les explications car elles sont assez technique, il faut quand même des connaissances en programmation. Juste une précision : Chez Mojang le code est certainement bien commenté et annoté et avec des noms de variables et fonctions explicites, c'est juste qu'avant chaque publication d'une version du jeu, celui-ci est volontairement obscurci après la compilation pour le rendre difficile à comprendre ou modifier pour quiconque voudrait l'analyser. Ils font cela et en parallèle soutiennent les moddeurs en leur disant que c'est super ce qu'on fait. Allez comprendre la logique :lol:

Re: Journal d'un développeur Java - Le code obfusqué

Publié : 09 oct. 2015, 16:31
par JoGoiA
A mon avis, il y a deux logiques en place ici :
- celle des concepteurs (comme Jeb ou autrefois Notch) qui veulent faire un jeu cool avec plein de gens super qui s'éclatent dessus
- Une logique d'entreprise un peu parano qui pense à tous les sous qu'ils ne gagneront pas si des petits malin peuvent bricoler eux-mêmes les jeux qu'ils aiment.

Ca donne un code obfusquer et des codeurs content qu'on tripatouille quand même leurs code :)

Re: Journal d'un développeur Java - Le code obfusqué

Publié : 09 oct. 2015, 22:09
par ORelio
A ma connaissance le code de Minecraft a toujours été obfusqué, après, savoir si ça date d'avant ou d'après la création de Mojang, aucune idée.
On comprend cependant les deux motivations, même si venant de Mojang c'est quand même un peu étrange ^^

Re: Journal d'un développeur Java - Le code obfusqué

Publié : 09 oct. 2015, 22:19
par foufou25
Oui il me semble aussi que le code Minecraft à été obfusqué.

(Terme Obfusqué :
Le terme obfusqué est désormais utilisé dans l'informatique lorsque certaines données d'un programme sont réécrites pour le rendre incompréhensible à la personne qui n'a pas le code.)

Re: Journal d'un développeur Java - Le code obfusqué

Publié : 11 oct. 2015, 14:22
par BigBen
Le java c'est pas trop mon truc mais beau petit journal ;)