La classe principale et les proxys


  • Administrateurs

    Maintenant que tout est prêt, nous allons pouvoir commencer à coder 🙂

    Commencez par faire défiler le dossier src, vous pourrez voir qu'il y a de nombreux packages. En fait c'est FML qui réorganise les sources de Minecraft afin d'être mieux triées.
    Par ailleurs vous avez aussi pu constater qu'il n'y a qu'un seul projet (à la place d'un pour le serveur et d'un pour le solo) car FML les a également regroupé. C'est grâce à ça que nous pouvons faire des mods "universal" (et surtout grâce au système de side, que nous verrons plus en détail plus tard).
    Créez maintenant un package, car contrairement à ML, Forge permet de créer son mod dans son propre package. Dans mon cas je vais l'appeler tutoriel.common

    La classe principale

    Dans le package que vous venez de créer, vous allez créer une première classe. Dans mon cas je vais l'appeler ModTutoriel. Avec ForgeModLoader, il est inutile de commencer le nom de sa classe par mod_
    Nous allons compléter cette classe avec quelques interfaces qui se trouvent dans l'interface Mod (cpw.mods.fml.common.Mod)
    Directement en dessous de la déclaration de package, nous allons ajouter @Mod. Vous allez avoir une erreur, passez la souris dessus, et cliquez sur import 'Mod' (cpw.mods.fml.common.Mod)
    Normalement @Mod devrait changer de couleur, mais il y a toujours une erreur. Cliquez maintenant sur "Add missing attributes". Après @Mod, il devrait s'ajouter ceci : (modid = "")
    Le modid correspond à l'id de votre mod, si FML détecte deux mods du même id, il va pensez que l'utilisateur a installé deux fois le même mod. Il est donc important d'utiliser un modid qui n'est pas utilisé par d'autres mods. Dans mon cas, je vais simplement reprendre le nom de ma classe principale :

    @Mod(modid = "ModTutoriel")
    

    On peut ajouter de nombreuses choses à ce @Mod, en les séparant par des virgules. Je vais donc faire le tour de tout ce qui se trouve dans l'interface @Mod.

    • String modid() c'est le mod id, il n'a pas de valeur par défaut, c'est pour ça que nous sommes obligés de le remplir
    • String name() c'est le nom de votre mod, celui qui s'affiche dans la liste des mods. Dans mon cas je vais mettre "Mod Tutoriel"
    • String version() c'est la version de votre mod, dans mon cas je vais mettre "1.0.0"

    Voilà, ce sont les trois plus importants, ma classe principale ressemble maintenant à ça :

    package tutoriel.common;
    
    import cpw.mods.fml.common.Mod;
    
    @Mod(modid = "ModTutoriel", name = "Mod Tutoriel", version = "1.0.0")
    
    public class ModTutoriel
    {
    
    }
    

    Je vais quand même en décrire quelques autres, ça peut toujours être utile :

    • String dependencies() Permet de faire des dépendances d'autres mods. Par exemple "required-after:Forge@[7.8.1,)" forcera l'utilisateur à avoir une version de forge supérieur au build 737 (Forge est le modid, si vous voulez le faire avec un autre mod, il faut aussi utiliser le modid
    • boolean useMetadata() Soit true, soit false, par défaut false. Cela n'a rien à voir avec les metadatas de blocs ou d'items, s'il est en true, vous pourrez intégrer le mcmod.info à l’intérieur de votre classe principale, comme Forge ou FML.
    • String acceptedMinecraftVersions() Ce sont les versions de Minecraft acceptées par votre mod. Il faut utiliser le "maven version range", voir ici
    • String certificateFingerprint() On peut l'utiliser pour faire un système de vérification, (par exemple dans le cas où vous avez Forestry et IndustrialCraft d'installés, Forestry va vérifier si IC2 n'est pas "trafiqué", si jamais il est modifié votre jeu se coupera). En revanche, je ne sais pas comment le faire fonctionner, si quelqu'un a des informations là-dessus, je prends
    • String modLanguage() par défaut java, on peut aussi créer des mods en scala

    Dans la classe principale en dessous de @Mod, ajouter @NetworkMod.
    Pour l'instant, nous allons juste utiliser les deux booleans clientSideRequired et serverSideRequired :

    @NetworkMod(clientSideRequired = true, serverSideRequired = false)
    

    clientSideRequired signifie que le client doit avoir le mod pour rejoindre un serveur où le mod est installé. Il faut le mettre en true, sauf si votre mod n'ajoute que des choses qu'ajouterai un plugin (exemple, Dynmap Forge et Forge Essential on cette valeur sur false)
    serverSideRequired signifie que le serveur doit avoir le mod pour être rejoint par un client qui possède ce mod. Il faut donc le mettre en false, sauf si vous voulez que les utilisateurs possédant le mod ne puissent se connecter à aucun serveur sauf ceux qui ont le mod.
    Dans le @NetworkMod, vous pouvez aussi définir la version bound : versionBounds = "[1.0.0,1.2.0]" par exemple, fonctionne aussi avec le "maven version range", avec cette exemple, un client en version 1.0.1 du mod pourra se connecter sur un serveur qui possède la version 1.1.2 du mod. Pour globaliser, toutes les versions comprises entre 1.0.0 et 1.2.0 pourra se connecter à un serveur qui possède le mod.

    Bon maintenant que nous avons rempli ces deux interfaces, nous allons créer quelques fonctions dans notre classe principale.
    Pour ceux qui ont l'habitude de modloader, il ne faut surtout pas faire un extends BaseMod. Perdez cette habitude.
    ForgeModLoader détecte déjà notre mod grâce à l'interface @Mod, et les void d'init seront détectés grâce aux events que nous avons vu plus haut.
    Donc dans notre classe principale nous allons ajouter les trois méthodes importantes de FML, j'expliquerai plus bas à quoi elles servent. Voici le rendu final :

    package tutoriel.common;
    
    import cpw.mods.fml.common.Mod;
    import cpw.mods.fml.common.Mod.EventHandler;
    import cpw.mods.fml.common.Mod.Instance;
    import cpw.mods.fml.common.SidedProxy;
    import cpw.mods.fml.common.event.FMLInitializationEvent;
    import cpw.mods.fml.common.event.FMLPostInitializationEvent;
    import cpw.mods.fml.common.event.FMLPreInitializationEvent;
    import cpw.mods.fml.common.network.NetworkMod;
    
    @Mod(modid = "ModTutoriel", name = "Mod Tutoriel", version = "1.0.0", acceptedMinecraftVersions = "[1.6.2,)")
    @NetworkMod(clientSideRequired = true, serverSideRequired = false)
    
    public class ModTutoriel
    {
        @Instance("ModTutoriel")
        public static ModTutoriel instance;
    
        @EventHandler
        public void PreInit(FMLPreInitializationEvent event)
        {
    
        }
    
        @EventHandler
        public void Init(FMLInitializationEvent event)
        {
    
        }
    
        @EventHandler
        public void PostInit(FMLPostInitializationEvent event)
        {
    
        }
    }
    

    Il en existe d'autres, mais elles sont moins utilisées.
    Vous pouvez voir en passant que j'ai ajouté l'instance de mon mod, elle ne vous sera pas forcément utile, en revanche vous l'utiliserez si vous créez des mobs dans une classe différente, ou des packets.
    Dans le PreInit, nous allons placer les configurations, compléter et enregistrer nos blocs et items, et placer les achievements.
    Dans le Init, nous allons enregistrer les tileEntity, les Entity, les rendu, etc…
    Dans le PostInit, nous allons faire les dernières finissions, comme par exemple les enregistrements de langages ou de recettes.
    (voir plus bas pour un exemple de où vont être chaque chose)

    Les proxys

    Les proxys vont vous être utile pour toutes les méthodes à faire sur un seul side. Par exemple, si dans ma classe principale je mets une méthode qui n'existe qu'en client (par exemple quelques choses qui gèrent les rendus), le serveur va crasher au lancement avec une erreur de "NoClassDefFound". Afin d'éviter ces problèmes, on utilise les proxys.

    Dans votre classe principale, en dessous de public class <nom de la classe> { ajoutez ceci :

    @SidedProxy(clientSide = "tutoriel.proxy.TutoClientProxy", serverSide = "tutoriel.proxy.TutoCommonProxy")
    public static TutoCommonProxy proxy;
    

    clientSide est le chemin de ma classe TutoClientProxy, et serverSide le chemin de ma classe TutoCommonProxy. Dans mon cas j'ai placé mes proxys dans le package tutoriel.proxy, mais vous pouvez le placer dans deux packages différents si vous le voulez, à chacun(e) sa façon de s'organiser :).

    Maintenant allez dans votre classe ClientProxy, et faites un extends CommonProxy. Tous les void que vous placerez dans votre client proxy devrons être override. Au début, nous allons principalement utiliser les proxys pour faire quelque chose uniquement en solo, mais quand votre mod sera plus complexe, ils pourront ressembler à ça :
    https://github.com/BuildCraft/BuildCraft/blob/master/common/buildcraft/core/proxy/CoreProxy.java
    https://github.com/BuildCraft/BuildCraft/blob/master/common/buildcraft/core/proxy/CoreProxyClient.java

    Voici le rendu final avec un exemple :

    package tutoriel.common;
    
    import tutoriel.proxy.TutoCommonProxy;
    import cpw.mods.fml.common.Mod;
    import cpw.mods.fml.common.Mod.EventHandler;
    import cpw.mods.fml.common.Mod.Instance;
    import cpw.mods.fml.common.SidedProxy;
    import cpw.mods.fml.common.event.FMLInitializationEvent;
    import cpw.mods.fml.common.event.FMLPostInitializationEvent;
    import cpw.mods.fml.common.event.FMLPreInitializationEvent;
    import cpw.mods.fml.common.network.NetworkMod;
    
    @Mod(modid = "ModTutoriel", name = "Mod Tutoriel", version = "1.0.0", acceptedMinecraftVersions = "[1.6.2,)")
    @NetworkMod(clientSideRequired = true, serverSideRequired = false)
    
    public class ModTutoriel
    {
        @SidedProxy(clientSide = "tutoriel.proxy.TutoClientProxy", serverSide = "tutoriel.proxy.TutoCommonProxy")
        public static TutoCommonProxy proxy;
    
        @Instance("ModTutoriel")
        public static ModTutoriel instance;
    
        @EventHandler
        public void PreInit(FMLPreInitializationEvent event)
        {
            // Configuration
    
            // Blocks
    
            // Items
    
            // Achievements
        }
    
        @EventHandler
        public void Init(FMLInitializationEvent event)
        {
            // Registry
    
            // Mobs
    
            // Render<
            proxy.registerRender();
            // NetWork
    
            // Recipe
    
        }
    
        @EventHandler
        public void PostInit(FMLPostInitializationEvent event)
        {
            // Intégration avec les autres mods
    
        }
    }
    

    Dans ma méthode Init, j'ai mis proxy.registerRender, donc au chargement du mod le jeu va faire ce qu'il trouve dans le void registerRender qui se trouve dans mes proxy.
    J'ai également ajouté en commentaire là où je vais mettre chaque chose .

    package tutoriel.proxy;
    
    public class TutoCommonProxy
    {
        public void registerRender()
        {
            // rien ici, les rendus ne se font que sur le client
        }
    }
    
    package tutoriel.proxy;
    
    import net.minecraftforge.client.MinecraftForgeClient;
    
    public class TutoClientProxy extends TutoCommonProxy
    {
        @Override
        public void registerRender()
        {
            // ici mes futur client registry
        }
    }
    

    Voir sur github

    Voilà, les choses ennuyeuses sont faites, vous allez pouvoir commencer vos premiers blocs et items.


  • Administrateurs

    Pour ceux qui n'ont pas envie de tout relire, voici la liste des changements entre ce tutoriel pour la 1.6.2 et l'ancien pour la 1.5.2 :

    • @Init, @PreInit, @PostInit et tout les autres annotations sont obsolète, il faut maintenant utiliser @EventHandler
    • J'ai enlevé les informations sur ce qui est obsolète (modExclusionList et bukkitPlugin)
    • J'ai ajouté une information à propos du versionBounds dans @NetworkMod

    Bref, pas de grand changement ici, il y a juste les @EventHandler à mettre.



  • Bonjour

    D'abord merci pour ces tutos (en français ! 🙂 )

    je débute en java et en modding donc ne soyez pas étonné de la simplicité de mes questions :))

    Dans la classe pincipale du tuto "ModTutoriel" sous @EventHandler les 3 méthodes suivantes sont utilisées :PreInit() Init() PostInit() ; tu parle de load à un moment : "Dans ma méthode load, j'ai mis proxy.registerRender…" .
    Après recherche (Forge) j'ai vu 3 autres méthodes qui apparemment font la même chose , soit dans l'ordre : preInit() load() postInit() , (j'ai testé les 2 ensembles de méthodes dans le même code pas de différence apparemment).

    Qu'elle est la différence donc entre ces 2 ensembles MAJ d'anciennes méthodes? En gros lesquelles doit ont utiliser ?



  • Le nom de la méthode ne change rien, il faut juste que tu es l'event en argument et le @EventHandler au dessus.


  • Administrateurs

    J'ai modifier en "Dans ma méthode Init, j'ai mis proxy.registerRender…", c'est plus compréhensible comme ça. (j'avais reprit de l'ancien tutoriel)

    Comme kevin_68 l'a dit, le nom de la méthode ne change absolument rien, c'est l'annotation @EventHandler et l'argument FML(Post/Pre)InitializationEvent qui fait que la méthode va être chargé par FML. Tu peux mettre :
    [code_java]@EventHandler
    nimporteQuelNomDeMethode(FMLInitializationEvent event)
    {

    }[/code_java]
    Ça reviendra au même.



  • Merci beaucoup pour cette réponse rapide et précise.

    Obnubilé par le " @EventHandler " je n'avais pas capté que c'était nous qui créions ces méthodes; ces annotations " @quelquechose " ne me sont pas encore
    vraiment compréhensibles.
    Je sais que se sont des tags javadoc ,mais je pensais que cela ne concernait que le domaine des commentaires ,de la documentation du programme.
    Apparemment cela va plus loin ; si l'on omet le " @EventHandler " àMarchePu ! Donc cela a une action sur : l'exécution du programme, la compilation du code ?
    Je sais que cela relève de la connaissance de la programmation java , mais si vous aviez un début de réponse ou une piste à suivre pour cette utilisation spécifique de la javadoc ,je suis preneur ; les @quelquechose sont très utilisés dans le code minecraft.

    J'ai vu dans 'cpw.mods.fml.common.Mod' cette annotation :

    • // Mark this method for receiving an {@link FMLEvent} (in this case, it's the {@link FMLPreInitializationEvent})
    • {@literal @}EventHandler public void preInit(FMLPreInitializationEvent event){}
      J'en déduit(par recoupement) que ça crée un lien avec les ' FMLEvent' qu'on l'utilise comme ça : @EventHandler
      public void preInit(FMLPreInitializationEvent event){}
      Mais au niveau java j'aimerai trouver de la doc sur la syntaxe et le mécanisme de ce genre d'annotation; en faite je manque de mot clef pour faire une recherche sur internet . En gros comment s'appelle ce genre de technique en java ?

    Ceci juste au cas ou quelqu'un aurait quelques éléments de réponse .

    Et encore un grand merci pour les réponses à ma précédente question.



  • Tout ce que je peux te dire c'est qu'un @quelquehose est une annotation (ou @interface) et que l'annotation @EventHandler est elle-même sous deux autres annotations qui sont: @Retention(RetentionPolicy.RUNTIME) et @Target(ElementType.METHOD). Pour comprendre à quoi elles servent regarde ça:
    http://adiguba.developpez.com/tutoriels/java/tiger/annotations/



  • Merci kevin_68 pour ta réponse super rapide j'ai de quoi m'occuper un moment 🙂



  • Pourquoi dans:
    @Mod(modid = "ModTutoriel", name = "Mod Tutoriel", version = "1.0.0", acceptedMinecraftVersions = "[1.6.1,)")
    acceptedMinecraftVersions est inférieur ou égal à 1.6.1 alors que le tuto est en 1.6.2?

    Sa ne devrait pas être:
    @Mod(modid = "ModTutoriel", name = "Mod Tutoriel", version = "1.0.0", acceptedMinecraftVersions = "[1.6.2,)")

    ou encore:
    @Mod(modid = "ModTutoriel", name = "Mod Tutoriel", version = "1.0.0", acceptedMinecraftVersions = "[1.6.1]")
    vu que dans forge 1.6.2 on a remplacé - @Init, @PreInit, @PostInit par @EventHandler
    les vieilles versions de forge (1.6.1 ou 1.5.2…) ne sont donc pas logiquement capable de comprendre un mod fait pour la 1.6.2!



  • Le tuto a été rédigé en 1.6.1 la première fois et robin a oublié de changer ça.


  • Administrateurs

    [1.6.1,) = 1.6.1 et supérieurs pas inférieurs, relis la doc sur "maven version range"

    Et oui, je pense que je vais remplacer par 1.6.2, car un mod 1.6.2 n'est pas compatible 1.6.1 si tu utilise la classe ResourceLocation (due à changement de package)



  • Bonjour j'ai un petit problème assez conséquent le problème est que je n'est pas le package cpw.mods.fml.common.Mod pourtant l’installation était un succès.


  • Administrateurs

    Il te manque juste ce package ou tout les packages en cpw.mods.fml ?
    Vérifie aussi que tu as bien les packages en net.minecraftforge



  • Il ne me manque que celui la il me semble.

    :::

    cpw.mods.fml.client
    cpw.mods.fml.client.modloader
    cpw.mods.fml.client.registry
    cpw.mods.fml.common
    cpw.mods.fml.common.asm
    cpw.mods.fml.common.asm.transformers
    cpw.mods.fml.common.asm.transformers.deobf
    cpw.mods.fml.common.discovery
    cpw.mods.fml.common.discovery.asm
    cpw.mods.fml.common.event
    cpw.mods.fml.common.functions
    cpw.mods.fml.common.launcher
    cpw.mods.fml.common.modloader
    cpw.mods.fml.common.network
    cpw.mods.fml.common.patcher
    cpw.mods.fml.common.registry
    cpw.mods.fml.common.toposort
    cpw.mods.fml.common.versioning
    cpw.mods.fml.relauncher
    cpw.mods.fml.repackage.com.nothome.delta
    cpw.mods.fml.server
    ibxm
    net.minecraft.block
    net.minecraft.block.material
    net.minecraft.client
    net.minecraft.client.audio
    net.minecraft.client.entity
    net.minecraft.client.gui
    net.minecraft.client.gui.achievement
    net.minecraft.client.gui.inventory
    net.minecraft.client.gui.mco
    net.minecraft.client.main
    net.minecraft.client.mco
    net.minecraft.client.model
    net.minecraft.client.multiplayer
    net.minecraft.client.particle
    net.minecraft.client.renderer
    net.minecraft.client.renderer.culling
    net.minecraft.client.renderer.entity
    net.minecraft.client.renderer.texture
    net.minecraft.client.renderer.tileentity
    net.minecraft.client.resources
    net.minecraft.client.resources.data
    net.minecraft.client.settings
    net.minecraft.client.stats
    net.minecraft.command
    net.minecraft.crash
    net.minecraft.creativetab
    net.minecraft.dispenser
    net.minecraft.enchantment
    net.minecraft.entity
    net.minecraft.entity.ai
    net.minecraft.entity.ai.attributes
    net.minecraft.entity.boss
    net.minecraft.entity.effect
    net.minecraft.entity.item
    net.minecraft.entity.monster
    net.minecraft.entity.passive
    net.minecraft.entity.player
    net.minecraft.entity.projectile
    net.minecraft.inventory
    net.minecraft.item
    net.minecraft.item.crafting
    net.minecraft.logging
    net.minecraft.nbt
    net.minecraft.network
    net.minecraft.network.packet
    net.minecraft.network.rcon
    net.minecraft.pathfinding
    net.minecraft.potion
    net.minecraft.profiler
    net.minecraft.scoreboard
    net.minecraft.server
    net.minecraft.server.dedicated
    net.minecraft.server.gui
    net.minecraft.server.integrated
    net.minecraft.server.management
    net.minecraft.src
    net.minecraft.stats
    net.minecraft.tileentity
    net.minecraft.util
    net.minecraft.village
    net.minecraft.world
    net.minecraft.world.biome
    net.minecraft.world.chunk
    net.minecraft.world.chunk.storage
    net.minecraft.world.demo
    net.minecraft.world.gen
    net.minecraft.world.gen.feature
    net.minecraft.world.gen.layer
    net.minecraft.world.gen.structure
    net.minecraft.world.storage
    net.minecraftforge.classloading
    net.minecraftforge.client
    net.minecraftforge.client.event
    net.minecraftforge.client.event.sound
    net.minecraftforge.client.model
    net.minecraftforge.client.model.obj
    net.minecraftforge.client.model.techne
    net.minecraftforge.common
    net.minecraftforge.common.network
    net.minecraftforge.common.network.packet
    net.minecraftforge.event
    net.minecraftforge.event.brewing
    net.minecraftforge.event.entity
    net.minecraftforge.event.entity.item
    net.minecraftforge.event.entity.living
    net.minecraftforge.event.entity.minecart
    net.minecraftforge.event.entity.player
    net.minecraftforge.event.terraingen
    net.minecraftforge.event.world
    net.minecraftforge.fluids
    net.minecraftforge.liquids
    net.minecraftforge.oredict
    net.minecraftforge.transformers
    paulscode.sound.codecs

    :::



  • un Spoiler aurai étai bien … 😞


    Merci 😉


  • Administrateurs

    Étrange, supprime le dossier forge/mcp et relance l'installation de forge.
    Si le problème persiste, envoie-moi le fichier forge\mcp\logs\mcp.log



  • Je t'ai envoyer un mp



  • J'ai exactement le même problème que blackswan 😕 Si le problème a était trouver entre temps merci de m'en faire part ^^


  • Administrateurs

    Prend la dernière version de forge, et réinstalle ton JDK ainsi que ton JRE



  • A vrai dire c'est exactement ce que je viens de faire, car je commence dans le modding ^^' (Je vais quand même le faire au cas ou :P)

    –---
    Je vien de le refaire et toujours pas de cpw.mods.fml.common.Mod 😞 Est-ce que le ''Mod'' en question serais dans cpw.mods.fml.common MAIS en l'ouvrant ? 😕


Log in to reply