Customiser votre bloc


  • Administrateurs

    Dans ce tutoriel nous allons voir de nombreuses méthodes pour rendre votre bloc différent des autres.

    Quelques méthodes de Forge

    Le tour des méthodes forge va être vite fait, elle s'ajoute dans la parti Init de votre classe principale :

        MinecraftForge.setBlockHarvestLevel(bloc, metadata, toolClass, harvestLevel);
    

    Ce code permet de définir le niveau d'harvest de votre bloc
    bloc correspond à l'objet de votre bloc, metadata au metadata, toolClass est un String qui peut être "pickaxe", "shovel" ou "axe" et harvestLevel est le niveau d'harvest (0 = outils en or et bois, 1 = cobble, 2 = fer, 3 = diamant)

        MinecraftForge.setBlockHarvestLevel(bloc, metadata, toolClass);
    

    Les paramètres sont les même que haut dessus. Il permet de supprimé un niveau d'harvest déjà existant.

        MinecraftForge.removeBlockEffectiveness(block, metadata, toolClass);
    

    À nouveau, même paramètre que haut dessus. Cette fonction permet de supprimer l'efficacité (destruction plus rapide) d'un bloc avec un outils spécifique.

    Pour ces 3 fonctions, si vous ne mettez pas de metadata la fonction sera fait sur tous les metadata de 0 à 15.

    Les méthodes de Block.java

    Dans la classe Block.java il y a de très très nombreuses méthodes. Vous pouvez les réutiliser dans la classe de votre bloc, et vous allez voir qu'on peut faire beaucoup de truc avec, il faut juste être un minimum logique 😉

        public float getBlockHardness(World world, int x, int y, int z)
    

    Une méthode pour l'hardness du bloc avec les paramètres world, x, y et z. Cela peut être utilisé pour faire un hardness différent en fonction du metadata :

        public float getBlockHardness(World world, int x, int y, int z)
        {
            switch(world.getBlockMetadata(x, y, z))
            {
                case 0 :return 0.1F;
                case 1 : return 8F;
                case 2 : return 4F;
                case 3 : return 12F;
                case 4 : return 2F;
                case 5 : return 50F;
                default : return 3F;
            }
        }
    

        @SideOnly(Side.CLIENT)
        public Icon getBlockTexture(IBlockAccess blockaccess, int x, int y, int z, int side)
    

    Nous avons déjà eu l'occasion de l'utiliser dans le tutoriel sur les directions de bloc, IBlockAccess permet d'avoir de nombreux autre paramètre (blockaccess.getBlockTileEntity(x, y, z) par exemple, blockaccess.getBlockId(x, y, z) qui peut être utilisé pour des textures connectées, blockaccess.getBlockMaterial(x, y, z) et de nombreuses autres méthodes)
    Cette fonction ne gère que les textures du bloc sur la map, pas dans l'inventaire ni dans la main.


        @SideOnly(Side.CLIENT)
        public AxisAlignedBB getSelectedBoundingBoxFromPool(World world, int x, int y, int z)
        {
            return AxisAlignedBB.getAABBPool().getAABB((double)x + this.minX, (double)y + this.minY, (double)z + this.minZ, (double)x + this.maxX, (double)y + this.maxY, (double)z + this.maxZ);
        }
    

    Cette fonction est utilisé pour le petit cadre qui apparait lorsqu'on à la souris sur le bloc (en gros la hitBox pour la sélection du bloc)
    Vous pouvez changer les valeurs, par exemple rajouter + 0.25D pour avoir une hitbox plus grande ou - 0.25D pour l'inverse. À vous d'utiliser votre imagination pour faire quelque chose avec 🙂


        public AxisAlignedBB getCollisionBoundingBoxFromPool(World world, int x, int y, int z)
        {
            return AxisAlignedBB.getAABBPool().getAABB((double)x + this.minX, (double)y + this.minY, (double)z + this.minZ, (double)x + this.maxX, (double)y + this.maxY, (double)z + this.maxZ);
        }
    

    Même chose, mais cette fois-ci pour la hitbox de collision avec les entités. Par exemple la soulsand à une collision légèrement plus basse, c'est pour ça qu'on s'enfonce un peu dedans. ( (double)y + 0.995D à la place de (double)y + this.maxY par exemple)


        public boolean isOpaqueCube()
        {
            return true;
        }
    

    À mettre sur false si votre bloc n'est pas entier (pour éviter les bug de lumière et empêcher de poser de la redstone/torche dessus)


        public void updateTick(World world, int x, int y, int z, Random rand)
    

    Une fonction exécuté à chaque fois que le bloc est tické.


        @SideOnly(Side.CLIENT)
        public void randomDisplayTick(World world, int x, int y, int z, Random rand)
    

    Une fonction uniquement en client qui est exécuté de temps en temps de façon aléatoire. Elle peut être par exemple être utilisez pour spawner des particules.


        public void onBlockDestroyedByPlayer(World world, int x, int y, int z, int metadata)
    

    Un fonction exécuté lorsqu'un joueur détruit le bloc.


        public void onNeighborBlockChange(World world, int x, int y, int z, int neighborblockid)
    

    Une fonction exécuté lorsqu'un bloc change autour de ce bloc. Cette fonction peut être utilisé pour la redstone par exemple :

        public void onNeighborBlockChange(World world, int x, int y, int z, int neighborblockid)
        {
            if(world.isBlockIndirectlyGettingPowered(x, y, z) && world.getBlockPowerInput(x, y, z) > 8)
            {
            //Action à faire si le bloc est alimenté par un signale de redstone avec une force supérieur à 8.
            }
        }
    

        public int tickRate(World world)
        {
            return 10;
        }
    

    Défini la vitesse du tick du bloc (lié avec la fonction updateTick). 1 pour 20 être tické 20 fois par seconde et 20 pour une fois par seconde. En gros, combien de tick doivent passer dans le monde avant de ticker le bloc.


        public int quantityDropped(Random rand)
        {
            return 1;
        }
    

    Quantité de drop. L'argument Random peut être utilisé pour droper plusieurs items/blocs de façon aléatoire :

        public int quantityDropped(Random rand)
        {
            return 2 + rand.nextInt(5);
        }
    

    (drop entre 3 et 7 loots)


        public int idDropped(int metadata, Random rand, int fortune)
        {
            return this.blockID;
        }
    

    L'id dropé par le bloc. Vous pouvez droper un bloc/item différent en utilisant ClassePrincipale.leBloc.blockID ou ClassePrincipale.lItem.itemID (remplacer par Block ou Item la classe principale pour les items et blocs de minecraft)
    Le paramètre metadata peut être utilisé pour droper un bloc différent un fonction du metadata et le paramètre Random pour un drop aléatoire :

    public int idDropped(int metadata, Random rand, int fortune)
    {
        if(metadata == 0 && rand.nextInt(5) > 3)
        {
            return ModTutoriel.BlockTutorial.blockID;
        }
        else if(metadata == 0)
        {
            return 0;
        }
        else
        {
            return this.blockID;
        }
    }
    

    Avec ce code, si le metadata du bloc est 0 et que un nombre au hasard comprit entre 1 et 5 est supérieur à 3 je drop l'id du blocTutoriel, sinon si le metadata est toujours 0 je drop rien (0 est l'air donc rien) et sinon je drop cette id.
    Le paramètre fortune, correspond simplement au niveau de fortune du bloc.


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

    Nous l'avons déjà utilisé dans le tutoriel sur les blocs en metadata, il permet de définir le metadata dropé.


        public void onEntityWalking(World world, int x, int y, int z, Entity entity)
    

    Exécuté lorsqu'une entité marche sur le bloc. Par exemple :

        public void onEntityWalking(World world, int x, int y, int z, Entity entity)
        {
            entity.setFire(10);
        }
    

    Mettra le feu pendant 10 secondes à l'entity.


        public void onBlockClicked(World world, int x, int y, int z, EntityPlayer player)
    

    Effectué lorsque le joueur fait un clic gauche sur le bloc. Par exemple, avec un bloc indestructible comme la bedrock :

        public void onBlockClicked(World world, int x, int y, int z, EntityPlayer player)
        {
            if(!world.isRemote)
                player.addChatMessage("tu peux encore taper longtemps");
        }
    

        public void onEntityCollidedWithBlock(World world, int x, int y, int z, Entity entity)
    

    Effectué lorsqu'une entité entre en collision avec le bloc. Attention, le blocBound doit être plus petit que la collision, sinon l'entité ne rentrera jamais en collision avec le bloc (cf setBlockBounds et getCollisionBoundingBoxFromPool)


        protected boolean canSilkHarvest()
        {
            return true;
        }
    

    À dans votre bloc si voulez qu'il puisse être directement récupéré avec silktouch, cf : le verre.


        public void onBlockPlacedBy(World world, int x, int y, int z, EntityLivingBase living, ItemStack stack)
    

    Effectué lorsqu'une entité place le bloc. Nous l'avons déjà utilisé pour les directions de bloc.


        @SideOnly(Side.CLIENT)
        public int idPicked(World world, int x, int y, int z)
        {
            return this.blockID;
        }
    

    L'id obtenu lors qu'un pickup sur le bloc.


        public boolean isBlockReplaceable(World world, int x, int y, int z)
    

    Détermine si le bloc est remplaçable. Si le return est true, votre bloc sera comme l'eau ou la lave, c'est à dire qu'on pourra placer un autre bloc par dessus.


        public int getFlammability(IBlockAccess world, int x, int y, int z, int metadata, ForgeDirection face)
        {
            return un nombre entre 0 et 300;
        }
    

    Détermine la vitesse à la-quel le bloc va être consumé par le feu. Sur 300 le bloc sera directement détruit par le feu.


        this.setBurnProperties(this.blockID, 1, 1000);
    

    À mettre dans le constructeur du bloc, rend le bloc brulable. 1 est l'encouragement (de combien le bloc augmente la propagation du feu et 1000 est la flammability (la probabilité que le bloc prend feu)


        public boolean canEntityDestroy(World world, int x, int y, int z, Entity entity)
    

    Détermine si votre bloc peut être détruit par une entité (utilisé pour l'enderdragon et le wither)
    Par exemple :

        public boolean canEntityDestroy(World world, int x, int y, int z, Entity entity)
        {
            if (entity instanceof EntityWither)
            {
                return false;
            }
            else if (entity instanceof EntityDragon)
            {
                return false;
            }
        }
    

    Rendra votre bloc indestructible par l'ender dragon et les withers.


        public boolean isBeaconBase(World worldObj, int x, int y, int z, int beaconX, int beaconY, int beaconZ)
        {
            return true;
        }
    

    Rend votre bloc utilisable pour un beacon.

    Voilà, j'ai fais un tour de la plupart des méthodes intéressante, il en existe aussi d'autres, je ne les ai pas tous présentés. Pour certains void, vous allez dire "J'en fais quoi de ces méthodes vides". La réponse est simplement, ce que vous voulez, utilisez votre imagination et les paramètres pour faire des blocs très différent des autres. Je vous ai montré quelques exemple avec les paramètres world x y et z, des méthodes comme world.getBlockMetadata(x, y, z) qui sont bien pratique, mais il en existe de nombreuses autres, utilisez le raccourci ctrl + espace pour voir cette liste ;). (Même chose avec entity. et stack. )



  • Tuto simple mais util… Vivement la suite !! 🙂


  • Administrateurs

    Voilà, tutoriel terminé. Si vous souhaitez apporter des exemples à la suite, faite, c'est toujours mieux avec des exemples.



  • Moyen de faire la même chose avec les items genre pour les effets d'items enchantés ou autre ?



  • Salut,
    très bon tuto mais j'aimerais créer une led, noire lorsqu'elle est eteinte et verte lorsqu'elle est allumé mais je trouve pas comment faire, le code de la lampe de redstone n'est pas la même.

    Quelqu'un pourrait m'aider ? Merci
    PS : je modde sur forge et j'aimerais changé juste la texture, pas créer un nouveau block.


  • Administrateurs

    Si tu veux juste changer la texture, tu n'as pas besoin de mod pour ça, juste d'un ressourcepack.


  • Administrateurs

    Passe par un TileEntity

    @Override
    public TileEntity createTileEntity(World world, int metadata)
    {
    return new TileEntityTutorial();
    }
    
    public boolean hasTileEntity(int metadata)
    {
    return true;
    }
    
    @SideOnly(Side.CLIENT)
    public Icon getBlockTexture(IBlockAccess blockaccess, int x, int y, int z, int side)
    {
    TileEntity te = blockaccess.getBlockTileEntity(x, y, z);
    if(te != null && te instanceof TileEntityTutorial)
    {
    TileEntityTutorial tetuto = (TileEntityTutorial)te;
    return te.isEnable() ? this.iconGreen : this.iconDark
    }
    return this.getIcon(side, blockaccess.getBlockMetadata(x, y, z));
    }
    

    iconGreen et iconDark sont tes deux icônes. Ne supprime pas la méthode getIcon, elle est nécessaire pour l'icône en main, getBlockTexture ne fait que la texture sur le monde.

    TileEntityTutorial ->

    public class TileEntityTutorial extends TileEntity
    {
    private boolean enable;
    
    public void updateEntity()
    {
    enable = this.worldObj.isBlockIndirectlyGettingPowered(this.xCoord, this.yCoord, this.zCoord)
    }
    
    public boolean isEnable()
    {
    return enable;
    }
    
    public Packet getDescriptionPacket()
    {
    NBTTagCompound nbttagcompound = new NBTTagCompound();
    this.writeToNBT(nbttagcompound);
    return new Packet132TileEntityData(this.xCoord, this.yCoord, this.zCoord, 4, nbttagcompound);
    }
    
    public void onDataPacket(INetworkManager net, Packet132TileEntityData pkt)
    {
    this.readFromNBT(pkt.data);
    }
    }
    

    ÉDIT : n'oublie pas d'enregistrer ton TileEntity, sinon tu vas avoir des erreurs.
    http://www.minecraftforgefrance.fr/showthread.php?tid=106



  • Dans le TileEntityLedVerte, il me met une erreur a .data : "this.readFromNBT(pkt.data);"
    Ainsi que a isEnable, iconGreen, iconDark dans BlockLedVerte.

    Sinon, y a pas un moyen de le faire avec deux blocks ? Sa serais peut-être plus facile ?


  • Administrateurs

    Désolé, j'avais mal compris ta demande. Par contre, tu pourrais nous dire quelles sont tes erreurs?



  • Je les aie marqué dans le post précédent


  • Administrateurs

    Tu as bien préciser que iconGreen et iconBlack, correspondent aux bonnes textures?


  • Administrateurs

    Oups, c'est de ma faute. Dans ton TileEntity, ajoute :

    public void readFromNBT(NBTTagCompound nbtTag)
    {
    super.readFromNBT(nbtTag);
    enable = nbtTag.getBoolean("enable");
    }
    
    public void writeToNBT(NBTTagCompound nbtTag)
    {
    super.writeToNBT(nbtTag);
    nbtTag.setBoolean("enable", enable);
    }
    


  • => robin4002 : Y'a une erreur a setString
    => Superloup10 : Comment je fais pour mettre deux textures dans ma classe ?
    Je suis sur forge 1.6.2


  • Administrateurs

    setBoolean* 😕



  • Je dois mettre quoi pour iconGreen, iconDark, isEnable plz ?
    Parce que je vois pas du tout comment faire.
    Merci


  • Administrateurs

    public void registerIcons(IconRegister iconRegister)
    {
    iconGreen = iconRegister.registerIcon("modid:TextureVerte");
    iconDark = iconRegister.registerIcon("modid:TextureNoire");
    }
    
    

    Voilà pour la gestion des textures, après à toi de faire en sorte que la TextureNoire soit celle, par défaut.



  • Merci mais l'on ne peut pas utiliser cette méthode ?
    if(world.isBlockIndirectlyGettingPowered(x, y, z) && world.getBlockPowerInput(x, y, z) > 😎
    {
    //Action à faire si le bloc est alimenté par un signale de redstone avec une force supérieur à 8.
    }

    Parce que la je ne comprend pas le code que vous m'avez passé.
    Il y a une erreur a " return te.enable() "


  • Administrateurs

    -> return tetuto.isEnable()
    À nouveau, fail de ma part

    Et sinon dans le tileEntiy :

    public void updateEntity()
    {
    enable = this.worldObj.isBlockIndirectlyGettingPowered(this.xCoord, this.yCoord, this.zCoord) && this.worldObj.getBlockPowerInput(this.xCoord, this.yCoord, this.zCoord) > 8;
    }
    


  • "Type mismatch: cannot convert from Object to Icon" pour ton erreur corrigé 😛
    et quand je change "tetuto.isEnable()" par "TileEntityLedVerte.isEnable()" parce que j'imagine que sa fait référence à mon TileEntity mais maintenant sa me marque "Cannot make a static reference to the non-static method isEnable() from the type TileEntityLedVerte" et quand je veut fixer l'erreur, je peut changer
    "
    public boolean isEnable()
    {
    return enable;
    }
    "
    par
    "
    public static isEnable()
    {
    return enable;
    }
    "
    mais y a d'autres erreurs qui apparaissent, bref sa fait une impasse d'erreur
    Merci de ta patience 😃


  • Administrateurs

    La méthode ne doit pas être static.
    Envoie toute ta fonction getBlockTexture