SetBlockState qui ne fonctionne pas (opération binaires sur la metadata)



  • Bonjour,
    Alors j'ai un block avec plusieurs variantes et orientable (verticalement), quand je le pose, avec un variante en particulier, un autre block est posé, j'ai mis des print dans la fonction "onBlockPlacedBy" et je trouve ça un peu bizarre…

    @Override
        public void onBlockPlacedBy(World worldIn, BlockPos pos, IBlockState state, EntityLivingBase placer, ItemStack stack)
        {
    EnumFacing face = WorldUtil.getVerticalFacingFromEntity(placer, pos);
    Energy.log.info("Before : " + worldIn.getBlockState(pos) + " ; Given by function : " + state);
    worldIn.setBlockState(pos, state.withProperty(onGround, Boolean.valueOf(face.equals(EnumFacing.DOWN))), 3);
    Energy.log.info("State added in world : " + state.withProperty(onGround, Boolean.valueOf(face.equals(EnumFacing.DOWN))));
    Energy.log.info("Current state in world : " + worldIn.getBlockState(pos));
    
        try
    {
    TileEntityEntityDetector te = (TileEntityEntityDetector) worldIn.getTileEntity(pos);
    if(placer instanceof EntityPlayer) te.setOwner((EntityPlayer) placer);
    }
    catch (Exception e)
    {
    //Je ne veux pas que ça crash (comme c'est pas le bon block, pas le bon tile entity...)
    }
    }
    

    Et voici les logs qui vont avec :

    [22:33:18] [Server thread/INFO] [Energy/]: Before : energy:EntityDetector[detectionRange=range_5,killMods=false,onGround=false] ; Given by function : energy:EntityDetector[detectionRange=range_5,killMods=false,onGround=false] Les states avant que l'on change quelque chose
    [22:33:18] [Server thread/INFO] [Energy/]: State added in world : energy:EntityDetector[detectionRange=range_5,killMods=false,onGround=true] //Le state donné à setBlockState
    [22:33:18] [Server thread/INFO] [Energy/]: Current state in world : energy:Computer[facing=south] //Après l'ajout dans le world obtenu avec getBlockState
    

    C'est un peu bizarre…


  • Administrateurs

    Donc en gros quand tu poses le bloc il se transforme en energy:Computer ?!?



  • C'est très bizarre … Une solution serais peut-être de passer directement par onBlockPlaced.



  • @Robin oui
    @max ah oui ouais j'essaye demain

    Envoyé de mon RAINBOW LITE 4G en utilisant Tapatalk


  • Administrateurs

    Si tu remplaces :
    worldIn.setBlockState(pos, state.withProperty(onGround, Boolean.valueOf(face.equals(EnumFacing.DOWN))), 3);
    par :
    worldIn.setBlockState(pos, ClassePrincipale.tonBlock.getDefaultBlockState().withProperty(onGround, Boolean.valueOf(face.equals(EnumFacing.DOWN))), 3);
    ça fonctionne ?



  • Je vois ce soir chez moi 🙂

    EDIT : alors les deux solutions proposées ne changent rien, mais j'ai l'impression que c'est un problème de block state id. 
    J'ai retiré le block (le computer) qui est posé à la place du bon (l'entity detector) du registry et quand je réessaye de poser le block, je fais un clic dans le vide, il  y a l'animation mais aucun block est posé. Puis, j'ai créé une autre map, et cette fois-ci, le block est bien posé mais la propriété "onGround" n'est pas appliquée (je set un block avec "onGround" = true et quand je fais world.getBlockState, la valeur "onGround" est à false.
     J'ai regardé les block state ids (Block.BLOCKS_STATES_IDS) du state avec "onGround" = false et celui avec "onGround" = true, et il se trouve qu'ils sont le même id, donc je pense que ça vient de là comme mc les considères identiques, si quelqu'un sait comment résoudre ça… Je regarderais demain les blocks states ids du mauvais block qui est posé à la place de l'entity detector pour voir si ils ne seraient pas identiques pas hasard...



  • Up please


  • Administrateurs

    Tu peux envoyer le code de ton bloc ?



  • Voici :

    package net.mystical.energy.blocks;
    
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Map;
    
    import net.minecraft.block.Block;
    import net.minecraft.block.material.Material;
    import net.minecraft.block.properties.IProperty;
    import net.minecraft.block.properties.PropertyBool;
    import net.minecraft.block.properties.PropertyEnum;
    import net.minecraft.block.state.BlockState;
    import net.minecraft.block.state.IBlockState;
    import net.minecraft.creativetab.CreativeTabs;
    import net.minecraft.entity.EntityLivingBase;
    import net.minecraft.entity.player.EntityPlayer;
    import net.minecraft.item.Item;
    import net.minecraft.item.ItemStack;
    import net.minecraft.tileentity.TileEntity;
    import net.minecraft.util.BlockPos;
    import net.minecraft.util.EnumFacing;
    import net.minecraft.util.IStringSerializable;
    import net.minecraft.util.MathHelper;
    import net.minecraft.world.IBlockAccess;
    import net.minecraft.world.World;
    import net.minecraftforge.fml.relauncher.Side;
    import net.minecraftforge.fml.relauncher.SideOnly;
    import net.mystical.energy.mod.Energy;
    import net.mystical.energy.registry.BlocksRegistry;
    import net.mystical.energy.tileentity.TileEntityEntityDetector;
    import net.mystical.energy.world.WorldUtil;
    
    public class BlockEntityDetector extends BlockBaseContainer
    {
        private static Map <string, integer="">elements = new HashMap();
    
    public static final PropertyEnum detectionRange = PropertyEnum.create("detectionRange", EnumDetectorRange.class);
    public static final PropertyBool onGround = PropertyBool.create("onGround");
    public static final PropertyBool killMobs = PropertyBool.create("killMods");
    
    public BlockEntityDetector() 
    {
    super(Material.glass);
    this.setDefaultState(this.getDefaultState().withProperty(detectionRange, BlockEntityDetector.EnumDetectorRange.RANGE_5).withProperty(onGround, Boolean.valueOf(false)).withProperty(killMobs, Boolean.valueOf(false)));
    }
    
    @Override
    public void setBlockBoundsBasedOnState(IBlockAccess world, BlockPos pos) 
    {
    IBlockState state = world.getBlockState(pos);
    if(state.getValue(onGround))
    {
    this.setBlockBounds(0.25F, 0F, 0.25F, 0.75F, 0.15F, 0.75F);
    }
    else
    {
    this.setBlockBounds(0.25F, 0.85F, 0.25F, 0.75F, 1F, 0.75F);
    }
    }
    
    @Override
    public IBlockState onBlockPlaced(World worldIn, BlockPos pos, EnumFacing facing, float hitX, float hitY, float hitZ, int meta, EntityLivingBase placer)
    {
    Energy.log.info("Current state in world before : " + worldIn.getBlockState(pos));
    EnumFacing face = WorldUtil.getVerticalFacingFromEntity(placer, pos);
    IBlockState state = this.getStateFromMeta(meta).withProperty(onGround, Boolean.valueOf(face.equals(EnumFacing.DOWN)));
    Energy.log.info("Giving : " + state + " ; from meta " + meta + " and face : " + face);
    return state;
    //return super.onBlockPlaced(worldIn, pos, facing, hitX, hitY, hitZ, meta, placer);
    }
    
    @Override
        public void onBlockPlacedBy(World worldIn, BlockPos pos, IBlockState state, EntityLivingBase placer, ItemStack stack)
        {
    Energy.log.info("Before : " + worldIn.getBlockState(pos) + " ; Given by function : " + state);
    //EnumFacing face = WorldUtil.getVerticalFacingFromEntity(placer, pos);
    //worldIn.setBlockState(pos, BlocksRegistry.entityDetector.getDefaultState().withProperty(onGround, Boolean.valueOf(face.equals(EnumFacing.DOWN))), 3);
    Energy.log.info("Current state in world : " + worldIn.getBlockState(pos));
    
        try
    {
    TileEntityEntityDetector te = (TileEntityEntityDetector) worldIn.getTileEntity(pos);
    if(placer instanceof EntityPlayer) te.setOwner((EntityPlayer) placer);
    }
    catch (Exception e)
    {
    //Je ne veux pas que ça crash (comme c'est un autre block
    }
    }
    
    @Override
    public boolean isFullCube()
    {
    return false;
    }
    
    @Override
    public boolean isOpaqueCube()
    {
    return false;
    }
    
        @Override
        public boolean canProvidePower()
        {
            return true;
        }
    
        @Override
        public int getStrongPower(IBlockAccess worldIn, BlockPos pos, IBlockState state, EnumFacing side)
        {
        TileEntity te = worldIn.getTileEntity(pos);
        if(te instanceof TileEntityEntityDetector) return ((TileEntityEntityDetector)te).isDetectingEntity() ? 15 : 0;
        return 0;
        }
    
        @Override
        public int getWeakPower(IBlockAccess worldIn, BlockPos pos, IBlockState state, EnumFacing side)
        {
        TileEntity te = worldIn.getTileEntity(pos);
        if(te instanceof TileEntityEntityDetector) return ((TileEntityEntityDetector)te).isDetectingEntity() ? 15 : 0;
        return 0;
        }
    
    @Override
    public TileEntity createNewTileEntity(World world, int meta) 
    {
    return new TileEntityEntityDetector();
    }
    
    @Override
    public int damageDropped(IBlockState state)
        {
            return this.getMetaFromState(state);
        }
    
        @SideOnly(Side.CLIENT)
        @Override
        public void getSubBlocks(Item itemIn, CreativeTabs tab, List list)
        {
        Iterator it = elements.values().iterator();
        int meta;
        int metaKillMobs;
        while(it.hasNext())
        {
        meta = (Integer) it.next();
        list.add(new ItemStack(itemIn, 1, meta));
    
        metaKillMobs = meta | 8;
        list.add(new ItemStack(itemIn, 1, metaKillMobs));
        }
        }
    
        @Override
        public IBlockState getStateFromMeta(int meta)
        {
        boolean killMobs = (meta & 8) != 0;
        boolean onGround = (meta & 16) != 0;
        IBlockState st = BlocksRegistry.entityDetector.getDefaultState().withProperty(detectionRange, EnumDetectorRange.byMetadata(meta)).withProperty(this.killMobs, Boolean.valueOf(killMobs)).withProperty(this.onGround, Boolean.valueOf(onGround));
        //Energy.log.info("Given state : " + st + " from meta : " + meta + " ; " + killMobs + " ; " + onGround + " ; " + EnumDetectorRange.byMetadata(meta));
        //Energy.log.info("Corresponding id : " + Block.BLOCK_STATE_IDS.get(st));
        return st;
        }
    
        @Override
        public int getMetaFromState(IBlockState state)
        {
        int meta = 0 | ((EnumDetectorRange)state.getValue(detectionRange)).getMetadata();
        boolean killMobs = state.getValue(this.killMobs);
        boolean onGround = state.getValue(this.onGround);
        if(killMobs)
        {
        meta |= 8;
        }
        if(onGround)
        {
        meta |= 16;
        }
        //Energy.log.info("Given meta : " + meta + " from state : " + state + " ; " + killMobs + " ; " + onGround + " ; " + ((EnumDetectorRange)state.getValue(detectionRange)).getMetadata());
        //Energy.log.info("Corresponding id : " + Block.BLOCK_STATE_IDS.get(state));
            return meta;
        }
    
        @Override
        public String getItemVariantNameFromMeta(int meta) //Une fonction de mon cru pour l'enregistrement des rendus
        {
        String str = EnumDetectorRange.byMetadata(meta).getName();
        if(Boolean.valueOf((meta & 8) != 0))
        {
        str += "_killMobs";
        }
        return str;
        }
    
        @Override
        protected BlockState createBlockState()
        {
            return new BlockState(this, new IProperty[] {detectionRange, onGround, killMobs});
        }
    
    public enum EnumDetectorRange implements IStringSerializable
        {
    //Maximum metadata : 7 (on 3bits), others bits are for other properties
            RANGE_5(0, 5, "range_5");
    
            private static final EnumDetectorRange[] META_LOOKUP = new EnumDetectorRange[values().length];
    
            private final int meta;
            private final int range;
            private final String name;
    
            private EnumDetectorRange(int meta, int range, String name)
            {
                this.meta = meta;
                this.range = range;
                this.name = name;
                BlockEntityDetector.elements.put(name, meta);
            }
    
            public int getMetadata()
            {
                return this.meta;
            }
            public int getRange()
            {
                return this.range;
            }
    
            public static EnumDetectorRange byMetadata(int meta)
            {
                return META_LOOKUP[MathHelper.abs_int(meta % META_LOOKUP.length)];
            }
    
            @Override
    public String toString()
            {
                return this.name;
            }
    
            @Override
    public String getName()
            {
                return this.name;
            }
    
            static
            {
                EnumDetectorRange[] var0 = values();
                int var1 = var0.length;
    
                for (int var2 = 0; var2 < var1; ++var2)
                {
                    EnumDetectorRange var3 = var0[var2];
                    META_LOOKUP[var3.getMetadata()] = var3;
                }
            }
        }
    }
    
    

    Regarde les opérations binaires pour la metadata, c'est peut-être à cause de ça (première fois que je l'utilise).</string,>


  • Administrateurs

    Oula en effet ça ne me semble pas du tout bon.
    Ton bloc est sensé avoir combien d'état différent possible ?



  • Pour le binaire ? Je me suis inspiré d'un block vanilla et d'un tuto, mais j'ai pas tout compris (et bien appliqué je pense).
    Pour l'instant il peut avoir 4 états mais je compte rajouter différentes portées.


  • Administrateurs



  • Merci je lis ça

    EDIT : Après avoir lus le tuto et refais le code, j'ai n'ai plus de problème, c'était donc bien les blockstates que Minecraft confondait à cause de mon code.