• S'inscrire
    • Se connecter
    • Recherche
    • Récent
    • Mots-clés
    • Populaire
    • Utilisateurs
    • Groupes

    Créer un bloc avec des metadatas

    Les blocs
    1.7.x
    9
    44
    22751
    Charger plus de messages
    • Du plus ancien au plus récent
    • Du plus récent au plus ancien
    • Les plus votés
    Répondre
    • Répondre à l'aide d'un nouveau sujet
    Se connecter pour répondre
    Ce sujet a été supprimé. Seuls les utilisateurs avec les droits d'administration peuvent le voir.
    • Phenix246
      Phenix246 Rédacteurs dernière édition par robin4002

      youtubeCe tutoriel est également disponible en vidéo.

      Sommaire

      • Introduction
      • Pré-requis
      • Code
        • La classe principale
        • La classe du bloc
        • La classe de l’itemblock
        • Les noms et les textures
      • Bonus
      • Résultat
      • Crédits

      Introduction

      Bienvenue dans mon premier tutoriel qui aura pour but d’apprendre à réaliser des blocs avec des metadatas.
      Vous avez sûrement remarqué que certains blocs ont des metadatas, ce qui donne un nom du genre <nom dans le game data>:1, <nom dans le game data>:2 etc… Dans ce tutoriel, vous allez apprendre à créer plusieurs blocs en utilisant les metadatas, ce qui permet d’avoir 16 blocs sur un seul id ( metadata de 0 à 15 au maximum, vous pouvez en avoir moins).
      L’avantage des metadatas est donc de pouvoir mettre 16 blocs sur le même id (même si les ids ne sont plus vraiment visibles, il existe toujours, la limite des 4096 blocs), cela permet donc d’économiser les ids. Il existe aussi une autre façon d’utiliser ces metadatas que nous ne verrons pas dans ce tutoriel, par exemple on peut les utiliser comme information, c’est ce que Mojang fait avec beaucoup de blocs de Minecraft (exemple : direction de la porte, de la citrouille, des bûches, etc …).

      Pré-requis

      • Créer un bloc basique

      Code

      Petit rappel, un bloc est aussi un item, nous allons d’ailleurs voir clairement apparaître cet item dans ce tutoriel. Il faut donc deux classes, celle du bloc et celle de l’item associé au bloc (ItemBlock).

      La classe principale :

      Commençons par déclarer notre bloc, il se déclare comme tous les autres :

          public static Block blockMetadataTuto;
      

      Si vous avez déjà d’autres blocs déclarés, vous pouvez le déclarer à la suite :

          public static Block blockTutoriel, blockTutoriel2, blockMetadataTuto;
      

      et on déclare notre bloc de façon normale comme tous les autres.

              blockMetadataTuto = new BlockTutorielMetadata().setBlockName("metadataTuto").setHardness(1.5F).setResistance(10.0F).setCreativeTab(CreativeTabs.tabBlock);
      

      La seule différence est qu’il n’y a pas la fonction pour les textures, elles seront déclarées dans la classe de notre bloc puisqu’il faut une texture pour chaque metadatas.

      Nous allons maintenant enregistrer notre bloc avec une petite spécificité :

          GameRegistry.registerBlock(blockMetadataTuto, ItemBlockMetadataTutoriel.class, "block_tuto_metadata");
      

      blockMetadataTuto est le bloc. ItemBlockMetadataTutoriel.class et une nouvelle classe que nous allons créer. Il s’agit de l’item bloc dont nous avons déjà parlé plus tôt. “block_tuto_metadata” est le nom du bloc dans le game data, utilisé comme référence pour le bloc (pour le give, etc …).

      Créez la classe BlockTutorielMetadata avec net.minecraft.block.Block en superClass et ItemBlockMetadataTutoriel avec net.minecraft.item.ItemBlock en superClass.

      La classe du bloc :

      Tout comme un bloc basique créez le constructeur, pour l’instant rien de change d’un bloc classique :

      package fr.minecraftforgefrance.tutoriel.common;
      
      import net.minecraft.block.Block;
      import net.minecraft.block.material.Material;
      
      public class BlockTutorielMetadata extends Block
      {
          public BlockMetadata()
          {
              super(Material.rock);
          }
      }
      

      Ensuite ajoutez au-dessus du constructeur ceci :

          public static String[] subBlock = new String[] {"block1", "block2", "block3", "block4"};
          public IIcon[] iconArray = new IIcon[subBlock.length];
      

      Ceci est un tableau de chaîne de caractères. Je l’ai appelé subBlock, vous pouvez le nommer comme vous voulez. Nous allons utiliser ce tableau pour l’enregistrement des textures, et pour les noms. block1, block2, etc… correspondent aux noms des futurs .png et aux noms non-localisés, adaptez-les selon vos besoins. Je vous conseille d’utiliser un tableau cela permet de beaucoup simplifier le code vu que les variables à l’intérieur vont être utilisées pour plusieurs choses.
      En dessous, j’ai fait un tableau d’icônes, il va servir pour les textures. (Importez net.minecraft.util.IIcon; )

      Nous allons maintenant enregistrer les textures des différents blocs avec cette méthode :

          public void registerBlockIcons(IIconRegister iconRegister)
          {
              for(int i = 0; i < subBlock.length; i++)
              {
                  this.iconArray[ i] = iconRegister.registerIcon(ModTutoriel.MODID + ":" + subBlock*);
              }
          }
      

      La boucle for va permettre d’enregistrer toutes les icônes en fonction de la taille du tableau subBlock. Ainsi, si vous souhaitez ajouter un bloc de plus, il vous suffit de l’ajouter au tableau “subBlock” ;).

      Maintenant il faut ajouter la fonction pour voir les blocs dans la table créative :

          public void getSubBlocks(Item item, CreativeTabs tabs, List list)
          {
              for(int i = 0; i < subBlock.length; i++)
              {
                  list.add(new ItemStack(item, 1, i));
              }
          }
      

      À nouveau la boucle for nous simplifie la vie, le principe est le même qu’au-dessus. Pour les erreurs, faites ctrl + shift + o pour organiser les importations, pour List, choisissez “java.util.List”

      Il ne nous reste plus qu’à finaliser la texture, car pour l’instant notre bloc utilise l’icône “blockIcon” comme il est extends Block. Nous allons donc ajouter la fonction getIcon dans notre bloc :

          public IIcon getIcon(int side, int metadata)
          {
              if(metadata >= 0 && metadata < subBlock.length)
              {
                  return this.iconArray[metadata];
              }
              return this.iconArray[0];
          }
      

      La condition est très importante, en effet elle sert à éviter un java.lang.ArrayIndexOutOfBoundsException. Si par erreur le joueur se give le bloc avec un metadata négatif ou supérieur à la taille du tableau (avec /give <pseudo> <bloc> <quantité> <metadata>), il aura un bloc avec la texture du metadata 0. Sans la condition, le jeu crash.
      Pour ceux qui sont à l’aise avec les conditions ternaires, voici le code “simplifié” :

          public IIcon getIcon(int side, int metadata)
          {
              return metadata >= 0 && metadata < subBlock.length ? this.iconArray[metadata] : this.iconArray[0];
          }
      

      Enfin on va définir le drop du bloc de façon à avoir le bon metadata :

          public int damageDropped(int metadata)
          {
              return metadata;
          }
      

      Elle est assez importante, si vous ne la mettez pas tous vos blocs vont dropper le metadata 0 ce qui est un peu embêtant.

      La classe de l’itemblock :

      Commencez par ajouter un constructeur, et dans ce constructeur ajoutez la méthode this.setHasSubtypes(true);. Sans cette méthode, vous n’arriverez pas à vous give un metadata supérieur à 0.

      package fr.minecraftforgefrance.tutoriel.common;
      
      import net.minecraft.item.ItemBlock;
      
      public class ItemBlockMetadataTutoriel extends ItemBlock
      {
          public ItemBlockMetadataTutoriel(Block block)
          {
              super(block);
              this.setMaxDamage(0);
              this.setHasSubtypes(true);
          }
      }
      

      Ensuite, ajoutez cette fonction :

          public int getMetadata(int metadata)
          {
              return metadata;
          }
      

      Par défaut dans Item.java cette méthode renvoie sur 0, c’est pour ça qu’il est important de la mettre, sinon même avec un bloc de metadata 1 en main, lorsque vous le poserez, il deviendra un bloc de metadata 0. Donc si un jour vous avez ce problème, vous saurez que vous avez oublié de mettre cette méthode. C’est un oubli vite arrivé mais au moins vous savez d’où viendra l’erreur.

      Il faut aussi ajouter une fonction pour la texture :

          @SideOnly(Side.CLIENT)
          public IIcon getIconFromDamage(int metadata)
          {
              return this.field_150939_a.getIcon(2, metadata);
          }
      

      Il reste encore à faire la méthode pour le nom, c’est là que le tableau est utile, vous allez donc ajouter :

          public String getUnlocalizedName(ItemStack stack)
          {
              int metadata = stack.getItemDamage();
              if(metadata < 0 || metadata >= BlockTutorielMetadata.subBlock.length)
              {
                  metadata = 0;
              }
              return super.getUnlocalizedName() + "." + BlockTutorielMetadata.subBlock[metadata];
          }
      

      Une fois de plus, if(metadata < 0 || metadata >= BlockTutorielMetadata.subBlock.length) est une condition pour éviter un java.lang.ArrayIndexOutOfBoundsException.
      Le nom non localisé sera donc tile.<le nom dans setblockname(“”)>.<le nom dans le tableau type>.name

      Les noms et les textures :

      Allez dans votre dossier forge/src/main/resources/assets/votre_mod_id/textures/block/ et créez tous les fichiers .png correspondant aux noms que vous avez mis dans le tableau type. Retournez dans forge/src/main/resources/assets/votre_mod_id/lang, ouvrez le fichier en_US.lang, et ajoutez les noms :
      tile.<le nom dans setblockname(“”)>.<le nom dans le tableau type>.name=le nom localisé.
      Attention je vous rappelle qu’il ne doit pas y avoir d’espace entre « name= » et le nom du bloc. Exemple dans mon cas :

      tile.metadataTuto.block1.name=Metadata Block 1
      tile.metadataTuto.block2.name=Metadata Block 2
      tile.metadataTuto.block3.name=Metadata Block 3
      tile.metadataTuto.block4.name=Metadata Block 4
      

      Bonus

      La classe de l’item du bloc va être presque la même pour tous vos blocs avec des metadatas, seul BlockTutorielMetadata.subBlock va changer dans la fonction getUnlocalizedName. Il est possible d’utiliser la même classe pour tous vos items de bloc.
      Déclarez un tableau de String dans la classe de votre item de bloc et initialisez-le dans le constructeur. Dans la fonction getUnlocalizedName, remplacez BlockTutorielMetadata.subBlock par ce tableau :

      package fr.minecraftforgefrance.tutoriel.common;
      
      import cpw.mods.fml.relauncher.Side;
      import cpw.mods.fml.relauncher.SideOnly;
      import net.minecraft.block.Block;
      import net.minecraft.item.ItemBlock;
      import net.minecraft.item.ItemBlockWithMetadata;
      import net.minecraft.item.ItemStack;
      import net.minecraft.util.IIcon;
      
      public class ItemBlockMetadataTutoriel extends ItemBlock
      {
          private final String[] subName;
          public ItemBlockMetadataTutoriel(Block block, String[] subBlock)
          {
              super(block);
              this.setMaxDamage(0);
              this.setHasSubtypes(true);
              this.subName = subBlock;
          }
      
          @SideOnly(Side.CLIENT)
          public IIcon getIconFromDamage(int metadata)
          {
              return this.field_150939_a.getIcon(2, metadata);
          }
      
          public int getMetadata(int metadata)
          {
              return metadata;
          }
      
          public String getUnlocalizedName(ItemStack stack)
          {
              int metadata = stack.getItemDamage();
              if(metadata < 0 || metadata >= this.subName.length)
              {
                  metadata = 0;
              }
              return super.getUnlocalizedName() + "." + this.subName[metadata];
          }
      }
      

      Maintenant dans votre classe principale, remplacez :

              GameRegistry.registerBlock(blockMetadataTuto, ItemBlockMetadataTutoriel.class, "block_tuto_metadata");
      

      par :

              GameRegistry.registerBlock(blockMetadataTuto, ItemBlockMetadataTutoriel.class, "block_tuto_metadata", new Object[]{BlockTutorielMetadata.subBlock});
      

      BlockTutorielMetadata.subBlock correspond au tableau de string où se trouvent les noms des sous blocs.

      Ainsi si je souhaite ajouter un second bloc avec des metadatas (donc 2x16 au max, soit 32 blocs en deux ids ;)); il me suffit de suivre les sous parties La classe principale, La classe du bloc, Les noms et les textures et d’enregistrer mon second bloc avec :

              GameRegistry.registerBlock(blockMetadataTuto2, ItemBlockMetadataTutoriel.class, "block_tuto_metadata_2", new Object[]{BlockTutorielMetadata2.subBlock});
      

      La classe ItemBlockMetadataTutoriel reste la même pour les deux, et je peux encore en ajouter d’autres si besoin.

      Résultat

      Voir le commit sur github
      Le commit sur github montre clairement où ont été placés les fichiers, ainsi que ce qui a été ajouté et retiré dans le fichier.

      Crédits

      Rédaction :

      • Phenix246
      • robin4002

      Correction :

      • gagoi
      • FireDreft
      • @Pchom

      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

      1 réponse Dernière réponse Répondre Citer 0
      • bbcmh3
        bbcmh3 dernière édition par

        Bonsoir !
        C’est un trés bon tutoriel, comme tout ceux que vous faites ici !
        Tu expliques vraiment bien, merci j’ai tout compris et ça fonctionne cette fois-ci ! ;D

        1 réponse Dernière réponse Répondre Citer 0
        • Phenix246
          Phenix246 Rédacteurs dernière édition par

          merci, robin a rectifié certaine des explications donc je te dit aussi merci de sa part.
          J’espère que tu en profitera bien, pour ma part je suis à l’étape au dessus, celle où tu dépasse le nombre de metadatas autorisé (16), c’est devenu ma marque de fabrique.

          1 réponse Dernière réponse Répondre Citer 1
          • bbcmh3
            bbcmh3 dernière édition par

            Bah personnelement, je n’ai pas encore besoin d’avoir plus de 16 autorisés donc… ;D

            Ton mod à l’air assez cool ! Mais les images ne s’affichent pas ! ^^
            Je viens de voir que tu avais fait de la laine lumineuse ? Le mod que je suis en train de développer est justement un mod qui rajoute despierres lumineuses et plusieursautres choses que je révelerais plus tard…

            1 réponse Dernière réponse Répondre Citer 0
            • Phenix246
              Phenix246 Rédacteurs dernière édition par

              Mon site web est down et j’ai pas encore re-upload toutes les images

              1 réponse Dernière réponse Répondre Citer 0
              • A
                anguelwyvern dernière édition par

                J’aurais une question par rapport au sujet principal, j’ai regardez la vidéo youtube, j’ai saise que les métadata permettait de “économiser” les ID, ou faire genre des porte (fermé c’est un bloc, ouvert s’en est un autre), ça j’ai piger

                la vient ma question, en faite j’aimerais faire en sorte qu’un block drop autre chose
                (exemple block redstone, drop poudre redstone),

                qu’elle rapport avec les metadata ?

                (dans customisation du block, j’ai vue une ligne de code, avec (int metadata))
                d’ou ma question ^^

                ensuite 2 ème question,
                dans la vidéo à 14min il dis
                “i = 0 (égal)”

                es qu’il pense à une affectation ? ou vraiment à faire = ?

                je débute dans le modding, soyez gentil avec les coups de fouet 🙂

                1 réponse Dernière réponse Répondre Citer 0
                • utybo
                  utybo dernière édition par

                  Tu peux faire dropper des trucs différents selon la metadata du bloc
                  Exemple : le bloc jeSuisUnBloc drop des melons si il a la metadata 0, des citrouilles si il a une metadata 1…

                  Moddeur à la retraite et développeur de trucs en Java.

                  J'aide les gens comme je peux, alors si mon message v…

                  1 réponse Dernière réponse Répondre Citer 1
                  • A
                    anguelwyvern dernière édition par

                    oooooh ok je vois merci à toi 🙂

                    1 réponse Dernière réponse Répondre Citer 0
                    • utybo
                      utybo dernière édition par

                      Pour l’affectation (oui c’est une affectation), c’est juste pour la boucle for c’est la valeur qui va être incrémentée. Elle est ensuite utilisée pour le code dans la boucle. Si tu ne comprends pas la boucle for regarde sur google 🙂

                      Moddeur à la retraite et développeur de trucs en Java.

                      J'aide les gens comme je peux, alors si mon message v…

                      1 réponse Dernière réponse Répondre Citer 2
                      • A
                        anguelwyvern dernière édition par

                        en faite j’étudie en ce moment même les boucle, et j’avais un doute.

                        encore une fois merci, je me doutais de la chose, mais je voulais être sur ^^

                        dernière question si je veux faire en sorte que un block drop autre chose (genre redstone et poudre redstone)
                        il lui faut obligatoirement des metadata ?

                        1 réponse Dernière réponse Répondre Citer 0
                        • robin4002
                          robin4002 Moddeurs confirmés Rédacteurs Administrateurs dernière édition par

                          Non, pas besoin. Le paramètre metadata sert uniquement à faire des conditions pour droper quelque chose de différent en fonction du metadata, mais si tu n’as pas de metadata il suffit juste de ne pas mettre de condition et c’est bon.

                          1 réponse Dernière réponse Répondre Citer 0
                          • A
                            anguelwyvern dernière édition par

                            ok merci

                            PS: sa y est c’est bon j’ai réussi a faire drop mes minerai en les minant, merci beaucoup pour vos réponse

                            1 réponse Dernière réponse Répondre Citer 0
                            • Polygon48
                              Polygon48 dernière édition par

                              Bonsoir ! Voilà je viens juste poser une petite question 🙂

                              Voilà, je suis débutant et je voudrais comprendre quelque chose, je ne comprends pas comment utiliser les metadata après.

                              Par exemple pour la génération de minerais à un moment il faut entrer un metadata :

                              this.addOreSpawn(…

                              Ce que je n’arrive pas à comprendre c’est que une fois que j’ai suivis le tutoriel comment définir les metadata ? Comment savoir quel numéro appartient à quel metadata ?

                              J’espère que vous allez arriver à comprendre ce que je veux dire car c’est très flou … x)

                              Merci d’avance à tous ! 😉

                              Cordialement, Polygon48

                              1 réponse Dernière réponse Répondre Citer 0
                              • Phenix246
                                Phenix246 Rédacteurs dernière édition par robin4002

                                regarde la tableau :

                                public static String[] subBlock = new String[] {"block1", "block2", "block3", "block4"};
                                

                                “block1” est le metadata 0, “block2” est le metadata 1, pour faire simple leur position dans le tableau définie leur metadata.

                                Si ça ne répond pas à ta question, donne nous plus de détails sur ce que tu veux faire, que l’on puisse t’aider

                                1 réponse Dernière réponse Répondre Citer 1
                                • Polygon48
                                  Polygon48 dernière édition par

                                  @‘Phenix246’:

                                  regarde la tableau :

                                  public static String[] subBlock = new String[] {"block1", "block2", "block3", "block4"};
                                  

                                  :

                                  “block1” est le metadata 0, “block2” est le metadata 1, pour faire simple leur position dans le tableau définie leur metadata.

                                  Si ça ne répond pas à ta question, donne nous plus de détails sur ce que tu veux faire, que l’on puisse t’aider

                                  C’était exactement cela !
                                  Du coup au passage j’en profite :p, si je veux que mon Block1 drop un item que j’ai créé (par exemple une épée) comment je dois faire ?
                                  Et aussi, imaginons que je créer encore une nouvelle sorte de bloc, je vais donc recréer des metadata, du coup comment je vais devoir faire, car si dans le tableau de mon block je suis l’ordre -> Block1 = metadata 0, block2 = metadata 1 et que je m’arrête au bloc 4 donc block4 = metadata 3, dans ma nouvelle classe pour ma deuxième sorte de bloc je reprends dans l’ordre ou je m’étais arrêté dans l’autre ? Du coup : le bloc1 = metadata 4 ?

                                  Merci encore pour ta réponse ! 🙂

                                  Cordialement, Polygon48

                                  1 réponse Dernière réponse Répondre Citer 0
                                  • robin4002
                                    robin4002 Moddeurs confirmés Rédacteurs Administrateurs dernière édition par

                                    Non, si tu fais un autre bloc, ça reprend à 0. Chaque bloc a ces metadata.
                                    Pour les drop il faut passer par la fonction getItemDropped

                                    1 réponse Dernière réponse Répondre Citer 1
                                    • Polygon48
                                      Polygon48 dernière édition par

                                      @‘robin4002’:

                                      Non, si tu fais un autre bloc, ça reprend à 0. Chaque bloc a ces metadata.
                                      Pour les drop il faut passer par la fonction getItemDropped

                                      D’accord d’accord !

                                      Dernière question et merci d’ailleurs pour toutes ses réponses !

                                      Du coup lors de la génération de minerais, dans la méthode :

                                      
                                      (new WorldGenMinable(ModTutoriel.TutorialMetadata.blockID, 5, 12, Block.stone.blockID)).generate(world, rand, x + rand.nextInt(16), 16 + rand.nextInt(32), z + rand.nextInt(16));
                                      

                                      Ici on a

                                      
                                      ModTutoriel.TutorialMetadata.blockID
                                      

                                      Quand j’aurais finis de créer ma classe avec mes metadata, le blockId sera le nom du bloc définis dans le tableau et le metadata celui de celui-ci ?
                                      Merci encore 🙂

                                      Cordialement, Polygon48

                                      1 réponse Dernière réponse Répondre Citer 0
                                      • Phenix246
                                        Phenix246 Rédacteurs dernière édition par

                                        vieux système en 1.7 les “.blockID” ont totalement disparu :

                                        (new WorldGenMinable(ModTutoriel.TutorialMetadata, 5, 12, Blocks.stone)).generate(world, rand, x + rand.nextInt(16), 16 + rand.nextInt(32), z + rand.nextInt(16));
                                        
                                        1 réponse Dernière réponse Répondre Citer 0
                                        • Polygon48
                                          Polygon48 dernière édition par

                                          @‘Phenix246’:

                                          vieux système en 1.7 les “.blockID” ont totalement disparu :

                                          (new WorldGenMinable(ModTutoriel.TutorialMetadata, 5, 12, Blocks.stone)).generate(world, rand, x + rand.nextInt(16), 16 + rand.nextInt(32), z + rand.nextInt(16));
                                          

                                          Merci beaucoup !
                                          Enfin grâce à vous j’ai réussi !

                                          Dernière dernière question après je n’embête plus !

                                          Pour le drop Robin ma dit d’utiliser getItemDropped, j’ai essayé plusieurs chose mais je ne trouve pas comment dropper un block, par exemple if metata = 1 on return Monmod.Item1

                                          Cordialement, Polygon48

                                          1 réponse Dernière réponse Répondre Citer 0
                                          • Phenix246
                                            Phenix246 Rédacteurs dernière édition par

                                            public Item getItemDropped(int metadata, Random rand, int fortune)
                                            {
                                            return metadata == 1 ? Monmod.Item1 : Item.getItemFromBlock(this);
                                            }
                                            
                                            public int damageDropped(int metadata)
                                            {
                                            return metadata == 1 ? "damage" : 1;
                                            }
                                            
                                            public int quantityDropped(int metadata, int fortune, Random par3Random)
                                            {
                                            return "nombre d'items"
                                            }
                                            

                                            Je te donne en plus deux autre méthode dont tu peux avoir besoin (la damage de l’item que tu drop et la quantité dropé)

                                            1 réponse Dernière réponse Répondre Citer 0
                                            • 1
                                            • 2
                                            • 3
                                            • 1 / 3
                                            • Premier message
                                              Dernier message
                                            Design by Woryk
                                            Contact / Mentions Légales

                                            MINECRAFT FORGE FRANCE © 2018

                                            Powered by NodeBB