Les dalles


  • Administrateurs

    Dans ce tutoriel nous allons voir comment créer des dalles avec 8 métadatas maximum. Pourquoi 8 métadatas et non 16 ? Car les demi dalles utilisent deux metadata, un pour le bloc placé vers le bas, et un pour le bloc placé vers le haut.

    Dans la classe principale

    Comme d'habitude, on commence par déclarer les blocs :

    public static Block DoubleSlabTuto, SingleSlabTuto;
    

    Ensuite on complète dans le preinit :

        DoubleSlabTuto = new BlockSlabTutorial(2003, true).setHardness(2.0F).setResistance(10.0F).setStepSound(Block.soundStoneFootstep).setUnlocalizedName("TutorialSlab");
        SingleSlabTuto = new BlockSlabTutorial(2004, false).setHardness(2.0F).setResistance(10.0F).setStepSound(Block.soundStoneFootstep).setUnlocalizedName("TutorialSlab");
    

    Vous devrez avoir l'habitude de ce code, la seul différence est le constructeur, en effet il y a une boolean en plus, true pour la dalle double et false pour la dalle simple.

    Ensuite nous allons enregistrer les blocs :

        GameRegistry.registerBlock(DoubleSlabTuto, ItemBlockTutorialSlab.class, "DoubleSlabTuto");
        GameRegistry.registerBlock(SingleSlabTuto, ItemBlockTutorialSlab.class, "SingleSlabTuto");
    

    Même si vous ne voulez pas de metadata, il faut enregistrer un ItemBlock différent, il est nécessaire pour compléter une demi dalle.

    Vous avez normalement 4 erreurs, deux sur BlockSlabTutorial et deux sur ItemBlockTutorialSlab, nous allons commencez par créer la classe du bloc.

    La classe du bloc

    Faite un extends BlockStep et ajoutez le constructeur :

        public static final String[] StepTypes = new String[] {"tuto", "tutometa1", "diamond", "gold", "iron"};
    
        public BlockSlabTutorial(int id, boolean isdouble)
        {
            super(id, isdouble);
            if(!this.isDoubleSlab)
            {
                this.setLightOpacity(0);
            }
        }
    

    Le tableau de String StepTypes est tout les types de dalle, mettez un seul si vous le voulez pas de metadata, sinon vous pouvez monter jusqu'à 8.
    La condition sert à mettre l'opacité de la demi dalle sur 0 (pour éviter des bug d'ombre).

    Ensuite quelques méthodes :

        @SideOnly(Side.CLIENT)
        private static boolean isBlockSingleSlab(int id)
        {
            return id == ModTutoriel.SingleSlabTuto.blockID;
        }
    

    Mettez ici votreclasseprincipale.ladallesimple.blockID.

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

    Détermine l'id du pickupblock.

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

    Détermine l'id dropé. Pour la quantité dropée une méthode est déjà définie dans la classe BlockHalfSlab, et comme notre classe hérite celle-ci, nous avons pas besoin de remettre la méthode pour la quantité du drop.

        protected ItemStack createStackedBlock(int metadata)
        {
            return new ItemStack(ModTutoriel.SingleSlabTuto.blockID, 2, metadata & 7);
        }
    

    Une méthode pour l'itemstack.

        public String getFullSlabName(int metadata)
        {
            if(metadata < 0 || metadata >= StepTypes.length)
            {
                metadata = 0;
            }
    
            return super.getUnlocalizedName() + "." + StepTypes[metadata];
        }
    

    Une méthode pour le nom non localisé, il utilisera automatiquement les noms mis dans le tableau de String StepType. C'est la même que dans le tutoriel sur les metadatas.

        @SideOnly(Side.CLIENT)
        public void getSubBlocks(int id, CreativeTabs creativeTabs, List list)
        {
            if(id != ModTutoriel.DoubleSlabTuto.blockID)
            {
                for(int i = 0; i < StepTypes.length; i++)
                {
                    list.add(new ItemStack(id, 1, i));
                }
            }
        }
    

    Pour afficher dans l'inventaire créatif les différentes dalles en fonction du metadata.

    Et pour finir, le getIcon :

        @SideOnly(Side.CLIENT)
        public Icon getIcon(int side, int metadata)
        {
            int k = metadata & 7;
            return k == 0 ? ModTutoriel.BlockTutorial.getBlockTextureFromSide(side) : k == 1 ? ModTutoriel.TutorialMetadata.getIcon(side, 0) : k == 2 ? Block.blockDiamond.getBlockTextureFromSide(side) : k == 3 ? Block.blockGold.getBlockTextureFromSide(side) : Block.blockIron.getBlockTextureFromSide(side);
        }
    

    Il vous suffit à chaque fois de faire Block.nomduBloc.getBlockTextureFromSide(side) pour les blocs vanilla et ClassePrincipale.nomduBloc.getBlockTextureFromSide(side) pour les blocs de votre mod. Pour les blocs avec métadata, utilisez :
    getIcon(side, <le metadata voulu>)

    La classe de l'ItemBlock

    Cette classe est plutôt longue, je vais donc vous donner le rendu final et expliquer après :

    package tutoriel.common;
    
    import cpw.mods.fml.relauncher.Side;
    import cpw.mods.fml.relauncher.SideOnly;
    import net.minecraft.block.Block;
    import net.minecraft.entity.player.EntityPlayer;
    import net.minecraft.item.ItemBlock;
    import net.minecraft.item.ItemStack;
    import net.minecraft.util.Icon;
    import net.minecraft.world.World;
    
    public class ItemBlockTutorialSlab extends ItemBlock
    {
        private final boolean isFullBlock;
        private final Block theHalfSlab;
        private final Block doubleSlab;
    
        public ItemBlockTutorialSlab(int id)
        {
            super(id);
            this.theHalfSlab = ModTutoriel.SingleSlabTuto;
            this.doubleSlab = ModTutoriel.DoubleSlabTuto;
            if(id - 256 == ModTutoriel.DoubleSlabTuto.blockID)
            {
                this.isFullBlock = true;
            }
            else
            {
                this.isFullBlock = false;
            }
            this.setMaxDamage(0);
            this.setHasSubtypes(true);
        }
    
        @SideOnly(Side.CLIENT)
        public Icon getIconFromDamage(int metadata)
        {
            return Block.blocksList[this.itemID].getIcon(2, metadata);
        }
    
        public int getMetadata(int metadata)
        {
            return metadata;
        }
    
        public String getUnlocalizedName(ItemStack stack)
        {
            return ((BlockSlabTutorial)theHalfSlab).getFullSlabName(stack.getItemDamage());
        }
    
        public boolean onItemUse(ItemStack stack, EntityPlayer player, World world, int x, int y, int z, int side, float par8, float par9, float par10)
        {
            if(this.isFullBlock)
            {
                return super.onItemUse(stack, player, world, x, y, z, side, par8, par9, par10);
            }
            else if(stack.stackSize == 0)
            {
                return false;
            }
            else if(!player.canPlayerEdit(x, y, z, side, stack))
            {
                return false;
            }
            else
            {
                int i1 = world.getBlockId(x, y, z);
                int j1 = world.getBlockMetadata(x, y, z);
                int k1 = j1 & 7;
                boolean flag = (j1 & 8) != 0;
    
                if((side == 1 && !flag || side == 0 && flag) && i1 == this.theHalfSlab.blockID && k1 == stack.getItemDamage())
                {
                    if(world.checkNoEntityCollision(this.doubleSlab.getCollisionBoundingBoxFromPool(world, x, y, z)) && world.setBlock(x, y, z, this.doubleSlab.blockID, k1, 3))
                    {
                        world.playSoundEffect((double)((float)x + 0.5F), (double)((float)y + 0.5F), (double)((float)z + 0.5F), this.doubleSlab.stepSound.getPlaceSound(), (this.doubleSlab.stepSound.getVolume() + 1.0F) / 2.0F, this.doubleSlab.stepSound.getPitch() * 0.8F);
                        –stack.stackSize;
                    }
                    return true;
                }
                else
                {
                    return this.placeDoubleSlabFromTop(stack, player, world, x, y, z, side) ? true : super.onItemUse(stack, player, world, x, y, z, side, par8, par9, par10);
                }
            }
        }
    
        @SideOnly(Side.CLIENT)
        public boolean canPlaceItemBlockOnSide(World world, int x, int y, int z, int side, EntityPlayer player, ItemStack stack)
        {
            int i1 = x;
            int j1 = y;
            int k1 = z;
            int id = world.getBlockId(x, y, z);
            int meta = world.getBlockMetadata(x, y, z);
            int j2 = meta & 7;
            boolean flag = (meta & 8) != 0;
    
            if((side == 1 && !flag || side == 0 && flag) && id == this.theHalfSlab.blockID && j2 == stack.getItemDamage())
            {
                return true;
            }
            else
            {
                if(side == 0)
                {
                    --y;
                }
    
                if(side == 1)
                {
                    ++y;
                }
    
                if(side == 2)
                {
                    --z;
                }
    
                if(side == 3)
                {
                    ++z;
                }
    
                if(side == 4)
                {
                    --x;
                }
    
                if(side == 5)
                {
                    ++x;
                }
    
                id = world.getBlockId(x, y, z);
                meta = world.getBlockMetadata(x, y, z);
                j2 = meta & 7;
                flag = (meta & 8) != 0;
                return id == this.theHalfSlab.blockID && j2 == stack.getItemDamage() ? true : super.canPlaceItemBlockOnSide(world, i1, j1, k1, side, player, stack);
            }
        }
    
        private boolean placeDoubleSlabFromTop(ItemStack stack, EntityPlayer player, World world, int x, int y, int z, int side)
        {
            if(side == 0)
            {
                --y;
            }
    
            if(side == 1)
            {
                ++y;
            }
    
            if(side == 2)
            {
                --z;
            }
    
            if(side == 3)
            {
                ++z;
            }
    
            if(side == 4)
            {
                --x;
            }
    
            if(side == 5)
            {
                ++x;
            }
    
            int i1 = world.getBlockId(x, y, z);
            int j1 = world.getBlockMetadata(x, y, z);
            int k1 = j1 & 7;
    
            if(i1 == this.theHalfSlab.blockID && k1 == stack.getItemDamage())
            {
                if(world.checkNoEntityCollision(this.doubleSlab.getCollisionBoundingBoxFromPool(world, x, y, z)) && world.setBlock(x, y, z, this.doubleSlab.blockID, k1, 3))
                {
                    world.playSoundEffect((double)((float)x + 0.5F), (double)((float)y + 0.5F), (double)((float)z + 0.5F), this.doubleSlab.stepSound.getPlaceSound(), (this.doubleSlab.stepSound.getVolume() + 1.0F) / 2.0F, this.doubleSlab.stepSound.getPitch() * 0.8F);
                    --stack.stackSize;
                }
    
                return true;
            }
            else
            {
                return false;
            }
        }
    }
    

    this.theHalfSlab = ModTutoriel.SingleSlabTuto;
    this.doubleSlab = ModTutoriel.DoubleSlabTuto;
    Initialise les variables, remplacez ModTutoriel par votre classe principale.
    if(id - 256 == ModTutoriel.DoubleSlabTuto.blockID) […]
    Défini si le bloc est double ou simple. le - 256 est important car les id d'item sont augmentés de 256 automatiquement par minecraft (cf : le constructeur de Item.java)

    Pour les deux autres méthodes, vous devez les connaître, si ce n'est pas le cas retournez voir le tutoriel sur les metadatas de blocs (lien en dessous).
    getIconFromDamage est pour la texture de l'ItemBlock.
    getMetadata vous devrez aussi la connaître, si c'est pas le cas retournez ici
    getUnlocalizedName utilise la fonction getFullSlabName, que nous avons mit dans la classe du bloc dalle, n'oubliez pas de changer le cast dans le return par le nom de votre classe.
    La fonction onItemUse sert à placer le bloc, si une dalle existe déjà, le bloc sera complété et deviendra une double dalle.
    La fonction placeDoubleSlabFromTop sert à compléter une dalle déjà existante placée en haut.
    Et la fonction canPlaceItemBlockOnSide sert à définir si le joueur peut poser le bloc. (À nouveau vérification avec la dalle si elle est simple ou double).

    En se qui concerne les & 7 ce sont eux qui gèrent si la dalle est en bas ou en haut, ils ne sont pas là pour rien, et les & 8 servent pour vérifier si le metadata de l'item n'est pas trop haut, je rappelle que vous pouvez faire que jusqu'à 8 dalles en metadata :

    Finissions + rendu final

    N'oubliez pas de mettre à jour les fichiers de lang pour le nom en jeu. Le principale est le même que pour les blocs avec metadata, le tableau de String est utilisé pour le nom non localisé :
    Par exemple pour moi :

    tile.TutorialSlab.tuto.name=Tutorial Slab
    tile.TutorialSlab.tutometa1.name=Metadata Tutorial 1 Slab
    tile.TutorialSlab.diamond.name=Diamond Slab
    tile.TutorialSlab.gold.name=Gold Slab
    tile.TutorialSlab.iron.name=Iron Slab
    

    Rendu final sur Github

    Minecraft dalle moddé


  • Administrateurs

    Très bon tuto, merci Robin4002, grâce à toi, je vais enfin pouvoir mettre mes dalles à jour (elles étaient bloquées en 1.4.7)



  • Ce tuto me donne la dalle.

    ( GUGU42, HUMORISTE PROFESSIONEL )


  • Administrateurs

    Le pire c'est que ça m'a fait rire (bon en même temps c'est normal vu l'état de mon cerveau à cette heure).



  • Génial merci ! 😄



  • Merci pour le tutoriel ! 🙂

    Hey, @Gugu42 …
    Et si on confond les couleurs, on est ... Dalle-tonien ? o/



  • Lol ! le jeu de mot x), me^me moi je n'y aurai pas pensé :).



  • @'Kanar':

    Merci pour le tutoriel ! 🙂

    Hey, @Gugu42 …
    Et si on confond les couleurs, on est ... Dalle-tonien ? o/

    Je te proposer dalle-r faire nos blagues et jeux de mots ailleurs 😛



  • Salut, je viens juste de m'en rendre conte, mais comment faire pour changer de type de Material ? ^^'.
    Car ceux que j'ai créer sont en bois, et je suis obliger de le casser a la pioche pour le casser rapidement, au lieu de pouvoir le faire a la main ou avec une hache. Vu comment sont fais les constructeurs, je peux difficilement changer le Material.

    Merci d'avance.
    Cordialement.


  • Administrateurs

    Je sais pas du pourquoi j'ai fais un extends BlockStep alors que j'ai remis toutes les fonctions qui sont dans blockStep pour les modifier. Donc, tu as juste à changer l'extends en BlockHalfSlab à la place de BlockStep et de modifier le constructeur :
    super(id, isdouble) -> super(id, isdouble, Material.wood);



  • Ok merci ^^, je regarde sa 🙂


    Nickel :D, merci :).



  • merci pour le tuto jai enfin pu faire met dalle par contre j'ai un problème avec celle en matière transparent elle sont opaque


  • Administrateurs

    Tu rajoute isOpaqueCube et tu le met en true non ?



  • Non false.



  • bas j'ai essayez de mettre .isopaquecube(true) sa met sa comme erreur "The method isOpaqueCube() in the type Block is not applicable for the arguments (boolean)"



  • Nan dans la classe de ton cube il faut le mettre 😉



  • j'ai mis

    public boolean isOpaqueCube()
    {
    return false;
    }
    

    dans la classe de mon bloc met sa changez rien



  • Tu a fail ta balise war_machine :).
    Elle doive être comme sa:

    La dernière -> [/CODE_Java]
    La première -> [CODE_Java]


  • Administrateurs

    Juste java, c'est plus simple, en plus il y a même un bouton pour mettre du code java sur l'éditeur.
    Tes textures ont bien la transparence ?
    Sinon il faut mettre le renderAsNormalBlock sur false.



  • sa marche pas et met texture son bien transparente les bloc et les escalier avec cette texture marche nickel y a que les dalle qui me donne du fils retordre. voila le code

    package modTutoriel.common;
    
    import cpw.mods.fml.relauncher.Side;
    import cpw.mods.fml.relauncher.SideOnly;
    import java.util.List;
    import java.util.Random;
    
    import modTutoriel.common.modTutoriel;
    import net.minecraft.block.Block;
    import net.minecraft.block.BlockHalfSlab;
    import net.minecraft.block.material.Material;
    import net.minecraft.client.renderer.texture.IconRegister;
    import net.minecraft.creativetab.CreativeTabs;
    import net.minecraft.item.ItemStack;
    import net.minecraft.util.Icon;
    
    public class BlockSlabv0 extends BlockHalfSlab
    {
        /** The type of tree this slab came from. */
        public static final String[] woodType = new String[] {"v0", "p1", "birch", "jungle"};
    
        public BlockSlabv0(int par1, boolean par2)
        {
            super(par1, par2, Material.glass);
            this.setCreativeTab(CreativeTabs.tabBlock);
    
        }
    
        public boolean isOpaqueCube()
        {
            return false;
        }
    
        public boolean renderAsNormalBlock()
        {
            return false;
        }
    
        @SideOnly(Side.CLIENT)
    
        /**
         * From the specified side and block metadata retrieves the blocks texture. Args: side, metadata
         */
        public Icon getIcon(int par1, int par2)
        {
            return modTutoriel.v0.getIcon(par1, par2 & 7);
        }
    
        /**
         * Returns the ID of the items to drop on destruction.
         */
        public int idDropped(int par1, Random par2Random, int par3)
        {
            return modTutoriel.v0.blockID;
        }
    
        /**
         * Returns an item stack containing a single instance of the current block type. 'i' is the block's subtype/damage
         * and is ignored for blocks which do not support subtypes. Blocks which cannot be harvested should return null.
         */
        protected ItemStack createStackedBlock(int par1)
        {
            return new ItemStack(modTutoriel.v0.blockID, 2, par1 & 7);
        }
    
        /**
         * Returns the slab block name with step type.
         */
        public String getFullSlabName(int par1)
        {
            if(par1 < 0 || par1 >= woodType.length)
            {
                par1 = 0;
            }
    
            return super.getUnlocalizedName() + "." + woodType[par1];
        }
    
        @SideOnly(Side.CLIENT)
    
        /**
         * returns a list of blocks with the same ID, but different meta (eg: wood returns 4 blocks)
         */
        public void getSubBlocks(int par1, CreativeTabs par2CreativeTabs, List par3List)
        {
            if(par1 != modTutoriel.v0.blockID)
            {
                for(int j = 0; j < 1; ++j)
                {
                    par3List.add(new ItemStack(par1, 1, j));
                }
            }
        }
    
        @SideOnly(Side.CLIENT)
    
        /**
         * When this method is called, your block should register all the icons it needs with the given IconRegister. This
         * is the only chance you get to register icons.
         */
        public void registerIcons(IconRegister par1IconRegister)
        {}
    
    }