Compiler son mod


  • Administrateurs

    youtubeCe tutoriel est également disponible en vidéo.

    Sommaire

    Introduction

    Vous avez maintenant un mod bien complet, cependant seul vous êtes capable de l'utiliser depuis Eclipse. Votre mod est prêt pour une beta public voir pour une version stable ou pour votre serveur. Il faut le compiler afin d'avoir un .jar que nous allons placer dans le dossier mods. Heureusement avec Forge Gradle cette opération se fait en une commande (bien plus simple qu'avant où il fallait faire le zip/jar manuellement, ajouter les ressources, etc …). Pour que ce tutoriel ne soit pas trop court nous allons aussi voir quelques modifications possibles dans le build.gradle.

    Pré-requis

    Compiler son mod avec Gradle

    Comme dit dans l'introduction, il n'y a rien de plus simple. Dans un premier temps rendez-vous dans une console ouverte dans le dossier de Forge. La manipulation a déjà été vu dans le tutoriel sur l'installation de l'espace de travail de Forge. Pour ce qui aurait oublié, sous Windows il faut appuyer sur la touche shift puis faire un clic droit dans le dossier. Ouvrir une fenêtre de commande ici apparaîtra dans la liste. Cliquez dessus, une invite de commande va s'ouvrir avec le chemin du dossier de Forge écrit. Sous Linux la plupart des distributions intègre de base un menu Ouvrir un terminal ici lorsqu'on fait un clic droit dans un dossier. Pour les distributions n'intégrant pas ce menu ou pour OS X, ouvrez normalement un terminal puis tapez cd suivis du chemin du dossier (glisser déposer le dossier met automatiquement le chemin du dossier dans le terminal). Sous Mac OS X il semblerai que depuis la version 10.9 en faisant un clic droit dans un dossier une option pour ouvrir un terminal dans le dossier actuel se trouve dans le menu service (à confirmer, je n'ai pas de Mac).

    Dans la console tapez simplement la commande suivant :
    Windows :

    gradlew build
    

    Linux & Mac OS X :

    ./gradlew build
    

    Une fois le build terminé le fichier jar se trouvera dans le dossier forge/build/libs et par défaut sera nommé modid-1.0.jar. Le nom ainsi que la version peuvent être changé dans le fichier build.gradle ("archivesBaseName" est le nom et "version" est la version).

    Générer un jar pour le développement

    Si votre mod contient un api pour ajouter du contenu à votre mod (exemple l'api d'IndustrialCraft2 permet d'ajouter des recettes aux différentes machines de ce mod, celui de buildcraft permet d'ajouter des machines qui se connectent aux tuyaux, etc …), ou bien que votre mod est une bibliothèque contenant un certain nombre de fonctions utilitaires (exemple FFMT libs, codechicken core / code chicken libs), mettre à disposition des autres développeurs une archive pour le développement (donc une version du mod faite pour fonctionner sur Eclipse) leur sera très utile.
    En effet Minecraft étant obfusqué, le jar conçu pour fonctionner avec le jeu n'est pas compatible avec un environnement de développement.
    Pour cela rendez-vous dans le fichier build.gradle et ajoutez ceci (en dessous de processResources) :

    task devJar(type: Jar) {
       from(sourceSets.main.output) {
           include '**'
       }
       classifier = 'dev'
    }
    

    Si vous souhaitez que votre jar de dev contienne aussi les sources du mod, ajoutez entre l'accolade de la task et le from :

       from(sourceSets.main.allSource) {
           include 'nomDeVotrePackage/**/**'
       }
    

    Ce qui donne :

    task devJar(type: Jar) {
       from(sourceSets.main.allSource) {
           include 'nomDeVotrePackage/**/**'
       }
       from(sourceSets.main.output) {
           include '**'
       }
       classifier = 'dev'
    }
    

    Pensez bien à remplacer nomDeVotrePackage par ce qui correspond.
    Pour finir à la fin du fichier ajoutez ceci :

    build.dependsOn devJar
    
    artifacts {
       archives devJar
    }
    

    Maintenant lorsque vous aller faire la commande gradlew build vous aurez un second fichier dans le dossier buil/libs/ qui aura en plus dans son nom : "dev".

    Obfusquer son mod

    Lorsque vous compilez votre mod celui-ci se retrouve à moitié obfusqué afin d'être compatible avec Minecraft (qui est de base obfusqué). Si vous utilisez un logiciel comme JD-gui (logiciel permettant de décompiler un fichier java) vous pourrez constaté que toutes les fonctions et les fields de Minecraft que vous utilisez dans votre mod sont renommés en func_xxxx et field_xxxx. Cela protège un peu votre mod des potentielles personnes cherchant à voler votre mod, cependant c'est loin d'être incontournable. Au contraire avec de la patience et la liste des mappings de mcp il est facile d'avoir un code utilisable sur Eclipse.
    Pour protéger un peu plus votre mod je vous propose d’obfusquer une seconde fois votre mod. Cependant gardez à l'esprit qu'avec même beaucoup de patiente on pourra toujours décompiler votre mod. En effet Java est un langage qui est très facilement décompilable. Le but de cette partie va être d'obfusquer les variables propres à votre mod.
    Ajoutez à la fin du fichier build.gradle ceci :

    task obfJar(type: proguard.gradle.ProGuardTask, dependsOn: reobf) {
       inputs.file jar.archivePath
       ext {
           outDir = file("${buildDir}/proguard")
           obfuscatedJar = "${outDir}/${jar.baseName}-${jar.version}.jar"
       }
       outDir.mkdirs()
    
       injars jar.archivePath
       outjars obfuscatedJar
       libraryjars configurations.compile
       configuration 'proguard.pro'
    }
    
    task obfOutput(type: Jar, dependsOn: obfJar) {
       appendix = 'obf'
       from zipTree(obfJar.obfuscatedJar)
    }
    
    artifacts {
       archives obfOutput
    }
    
    build.dependsOn obfJar, obfOutput
    

    Au début du build.gradle, dans buildscript{ […] dependencies{, en dessous de la ligne :

           classpath 'net.minecraftforge.gradle:ForgeGradle:1.2-SNAPSHOT'
    

    Ajoutez :

           classpath 'net.sf.proguard:proguard-gradle:5.2.1'
    

    Maintenant dans le dossier de votre projet créez un fichier nommé proguard.pro. Ouvrez-le avec un éditeur de texte puis ajoutez ceci dedans :

    -libraryjars <java.home>/lib/rt.jar
    
    -dontoptimize
    -dontpreverify
    -dontwarn **
    -keepattributes *Annotation*
    
    -keep public class fr.minecraftforgefrance.tutoriel.** {
       public protected <methods>;
    }
    
    -keepclassmembers !public class fr.minecraftforgefrance.tutoriel.** {
       public protected <methods>;
    }
    
    -keep public class net.minecraft.** {
    *;
    }
    
    -keepclassmembers enum  * {
       public static **[] values();
       public static ** valueOf(java.lang.String);
    }
    

    Remplacez bien le package fr.minecraftforgefrance.tutoriel par le votre ! Pour plus d'information sur ce fichier rendez-vous ici.

    Maintenant lancez la commande gradlew build, dans le dossier build/libs vous devrez retrouvez deux fichiers jar, dont un avec -obf dans son nom.
    Voila une petite comparaison de la classe principale décompilé avec jd-gui :

    Comme vous pouvez le voir le code est bien plus difficile à comprendre sur le fichier de droite (donc celui obfusqué).

    En vidéo

    Youtube Video

    Crédits

    *Rédaction :

    Correction :

    Creative Commons
    Ce tutoriel de Minecraft Forge France est mis à disposition selon les termes de la licence Creative Commons Attribution - Pas d’Utilisation Commerciale - Partage dans les Mêmes Conditions 4.0 International

    retourRetour vers le sommaire des tutoriels



  • Bonjour, est il possible de desobfuscer un mods après avoir perdu la source ?
    Cordialement



  • Oui, regarde le BON2 (bearded octo nemesis) : https://github.com/Parker8283/BON2

    Attention : ton mod sera juste dé-obfusqué, ce qui veut dire que même une fois décompilé, les sources ne seront pas exactement les mêmes.



  • Bonjour, quand je fais gradlew build, une erreur est mise:

    FAILURE: Build failed with an exception.

    *What went wrong:
    Execution failed for task ':reobf'

    MALFORMED

    *Try:
    Run with –stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.

    Build FAILED

    Vous pouvez m'aider ?


  • Administrateurs

    Salut,
    Tu as surement des accents dans le nom des tes fichiers de textures voire pire dans le nom de tes classes.
    Ce n'est pas bon du tout.
    Seuls les caractères de A à Z, de a à z, de 0 à 9, les tirets et les tirets du bas doivent être utilisé.



  • Bonjour/bonsoir, j'ai une erreur pour l'étape obfOutput : http://prntscr.com/cthcwq

    Si vous pouviez m'aider, merci ! 🙂


  • Administrateurs

    les espaces et les ? dans le nom de la texture ce n'est pas du tout une bonne idée.



  • @'robin4002':

    les espaces et les ? dans le nom de la texture ce n'est pas du tout une bonne idée.

    Yep enfaite j'ai réussi ::p c'était le nom des textures qui étaient bug j'avais pas vu :')
    Mais j'ai encore un problème mais au lancement du mod obfusqué.
    http://prntscr.com/cthvzt


  • Administrateurs

    Visiblement le byte code est corrompu.
    Je peux voir ton fichier proguard.pro ?



  • @'robin4002':

    Visiblement le byte code est corrompu.
    Je peux voir ton fichier proguard.pro ?

    Le voici :

    -libraryjars 'C:\Program Files\Java\jre1.8.0_101\lib\rt.jar'
    
    -dontoptimize
    -overloadaggressively
    -useuniqueclassmembernames
    -keepattributes *Annotation*
    -adaptclassstrings
    -dontpreverify
    -dontwarn **
    
    -keep public class proxy.** {
       public protected <methods>;
    }
    
    -keep public class api.** {
       public protected <methods>;
    }
    
    -keepclassmembers !public class proxy.** {
       public protected <methods>;
    }
    
    -keepclassmembers !public class api.** {
       public protected <methods>;
    }
    
    -keep public class net.minecraft.**
    
    # Also keep - Enumerations. Keep the special static methods that are required in
    # enumeration classes.
    -keepclassmembers enum  * {
       public static **[] values();
       public static ** valueOf(java.lang.String);
    }
    ```</methods></methods></methods></methods>

  • Administrateurs

    Ajoutes :
    -keep public class ta.classe.principale



  • Toujours la même erreur 😞


  • Administrateurs

    Je ne sais pas d'où ça vient alors 😕



  • Tu peux teamviewer pour m'aider?


  • Administrateurs

    Désolé mais j'ai d'être priorité actuellement.
    Je n'ai pas vraiment le temps pour faire du support au cas par cas à distance.



  • J'ai réussi a réglé mon premier problème, mais j'ai ce problème maintenant : 
    http://prntscr.com/cttdxq


  • Administrateurs

    La version non obfusqué fonctionne-t-elle ?



  • @'robin4002':

    La version non obfusqué fonctionne-t-elle ?

    oui elle fonctionne


  • Administrateurs

    Le problème est ici :
    String apiPackage = data.getClassName().substring(0,data.getClassName().indexOf(".package-info"));
    data.getClassName().indexOf(".package-info") renvoies -1 (donc il n'a pas trouvé .package-info) en revanche je ne sais pas du tout à quoi cela correspond et donc je ne sais pas non plus comment corriger ça 😕



  • Moi ça me fait ça… Une idée 😕 ?