Problème de direction d'un projectile depuis un dispenser



  • Bonjour, depuis un petit moment je me suis lancé dans la création d'un mod pour lancer un projectile explosif depuis un dispenser. Le problème est que mon entité ne peut être lancée que vers le nord ou le sud sinon elle meure dès qu'elle spawn :
    Classe du dispenser :```java
    package fr.freshblock.freshrocket.common;

    import fr.freshblock.freshrocket.entity.projectile.EntityFreshRocket;
    import net.minecraft.block.BlockDispenser;
    import net.minecraft.client.model.ModelRenderer;
    import net.minecraft.dispenser.BehaviorDefaultDispenseItem;
    import net.minecraft.dispenser.IBlockSource;
    import net.minecraft.dispenser.IPosition;
    import net.minecraft.entity.Entity;
    import net.minecraft.item.ItemStack;
    import net.minecraft.util.EnumFacing;
    import net.minecraft.world.World;

    public final class BehaviorDefault extends BehaviorDefaultDispenseItem
    {
    @Override
    protected ItemStack dispenseStack(IBlockSource source, ItemStack stack)
    {
            //Obtenir le monde

    World world = source.getWorld();

    EnumFacing enumfacing = BlockDispenser.func_149937_b(source.getBlockMetadata());
            IPosition iposition = BlockDispenser.func_149939_a(source);

    //instancier l'entité

    Entity entityfreshrocket = new EntityFreshRocket(world, iposition.getX(), iposition.getY(), iposition.getZ());

    //vecteur x
            double x = source.getX();
            double x1 = iposition.getX();
            double dirX = x1-x;

    //vecteur y
            double y = source.getY();
            double y1 = iposition.getY();
            double dirY = y-y1;

    //vecteur z
            double z = source.getZ();
            double z1 = iposition.getZ();
            double dirZ = z-z1;

    entityfreshrocket.motionX = dirX;
            entityfreshrocket.motionY = dirY;
            entityfreshrocket.motionZ = dirZ;

    world.spawnEntityInWorld(entityfreshrocket);

    –stack.stackSize;
            return stack;
        }
    }
    Classe de l'entité:java
    package fr.freshblock.freshrocket.entity.projectile;

    import cpw.mods.fml.common.registry.EntityRegistry;
    import net.minecraft.block.Block;
    import net.minecraft.entity.Entity;
    import net.minecraft.entity.EntityLivingBase;
    import net.minecraft.entity.IProjectile;
    import net.minecraft.entity.monster.EntityBlaze;
    import net.minecraft.entity.player.EntityPlayer;
    import net.minecraft.entity.projectile.EntityThrowable;
    import net.minecraft.init.Blocks;
    import net.minecraft.nbt.NBTTagCompound;
    import net.minecraft.util.DamageSource;
    import net.minecraft.util.IProgressUpdate;
    import net.minecraft.util.MathHelper;
    import net.minecraft.util.MovingObjectPosition;
    import net.minecraft.util.MovingObjectPosition.MovingObjectType;
    import net.minecraft.world.Explosion;
    import net.minecraft.world.World;

    public class EntityFreshRocket extends EntityThrowable
    {
    private static final Block obsidian = Blocks.obsidian;
    private int xTile = -1; // Position X du projectile
        private int yTile = -1; // Position Y du projectile
        private int zTile = -1; // Postion Z du projectile
        private Block inTile;
        private int inData;
        private boolean inGround; // Dans un bloc ou pas
        public int arrowShake;
        public Entity shootingEntity; // Le joueur qui a tiré le projectile
        private int ticksInGround; // Je pense que c'est clair
        private int ticksInAir; // Je pense que c'est clair également
        private double damage = 6.0D; // Dégats du projectile
        private int knockbackStrength; // Puissance du knockback
        public int canBePickedUp;

    public void setThrowableHeading(double p_70186_1_, double p_70186_3_, double p_70186_5_, float p_70186_7_, float p_70186_8_)
        {
            this.renderDistanceWeight = 10.0D;
            this.setSize(0.5F, 0.5F);
            this.setPosition(p_70186_3_, p_70186_5_, p_70186_7_);
            this.yOffset = 0.0F;
        }

    public EntityFreshRocket(World worldIn)
        {
            super(worldIn);
            this.renderDistanceWeight = 10.0D; // Si je comprend bien, la distance
                                               // du render de la flèche
            this.setSize(0.5F, 0.5F); // taille du projectile
        }

    public EntityFreshRocket(World worldIn, double x, double y, double z)
        {
            super(worldIn);
            this.renderDistanceWeight = 10.0D; // Pareil qu'au dessus
            this.setSize(0.5F, 0.5F); // Pareil qu'au dessus
            this.setPosition(x, y, z); // La position du projectile
        }

    public EntityFreshRocket(World worldIn, EntityLivingBase shooter, EntityLivingBase p_i1755_3_, float p_i1755_4_, float p_i1755_5_)
        {
            super(worldIn);
            this.renderDistanceWeight = 10.0D; // Toujours pareil
            this.shootingEntity = shooter; // Qui a tiré le projectile

    if(shooter instanceof EntityPlayer)
            {
                this.canBePickedUp = 0; // Si le tireur peut ramasser le projectile
            }
            // Plein de méthode chelous...
            this.posY = shooter.posY + (double)shooter.getEyeHeight() - 0.10000000149011612D;
            double d0 = p_i1755_3_.posX - shooter.posX;
            double d1 = p_i1755_3_.getBoundingBox().minY + (double)(p_i1755_3_.height / 3.0F) - this.posY;
            double d2 = p_i1755_3_.posZ - shooter.posZ;
            double d3 = (double)MathHelper.sqrt_double(d0 * d0 + d2 * d2);

    if(d3 >= 1.0E-7D)
            {
                float f2 = (float)(Math.atan2(d2, d0) * 180.0D / Math.PI) - 90.0F;
                float f3 = (float)(-(Math.atan2(d1, d3) * 180.0D / Math.PI));
                double d4 = d0 / d3;
                double d5 = d2 / d3;
                this.setLocationAndAngles(shooter.posX + d4, this.posY, shooter.posZ + d5, f2, f3);
                float f4 = (float)(d3 * 0.20000000298023224D);
                this.setThrowableHeading(d0, d1 + (double)f4, d2, p_i1755_4_, p_i1755_5_);
            }
        }

    public EntityFreshRocket(World worldIn, EntityLivingBase shooter, float p_i1756_3_) // Quasiment la mème qu'au dessus
        {
            super(worldIn);
            this.renderDistanceWeight = 10.0D;
            this.shootingEntity = shooter;

    if(shooter instanceof EntityPlayer)
            {
                this.canBePickedUp = 0;
            }

    this.setSize(0.5F, 0.5F);
            this.setLocationAndAngles(shooter.posX, shooter.posY + (double)shooter.getEyeHeight(), shooter.posZ, shooter.rotationYaw, shooter.rotationPitch);
            this.posX -= (double)(MathHelper.cos(this.rotationYaw / 180.0F * (float)Math.PI) * 0.16F);
            this.posY -= 0.10000000149011612D;
            this.posZ -= (double)(MathHelper.sin(this.rotationYaw / 180.0F * (float)Math.PI) * 0.16F);
            this.setPosition(this.posX, this.posY, this.posZ);
            this.motionX = (double)(-MathHelper.sin(this.rotationYaw / 180.0F * (float)Math.PI) * MathHelper.cos(this.rotationPitch / 180.0F * (float)Math.PI));
            this.motionZ = (double)(MathHelper.cos(this.rotationYaw / 180.0F * (float)Math.PI) * MathHelper.cos(this.rotationPitch / 180.0F * (float)Math.PI));
            this.motionY = (double)(-MathHelper.sin(this.rotationPitch / 180.0F * (float)Math.PI));
            this.setThrowableHeading(this.motionX, this.motionY, this.motionZ, p_i1756_3_ * 1.5F, 1.0F);
        }

    protected void onImpact(MovingObjectPosition EntityFreshRocket)
        {
        //If this hit's a block, continue
        if(EntityFreshRocket.typeOfHit == MovingObjectType.BLOCK)
        {
        /*
        * You might be wondering what
        * all these case and break are
        * These are use to switch the number
        * EntityFreshRocket.sideHit
        *
        * Example:
        * If EntityFreshRocket.sideHit == 3 whatever is in
        * case 3 Happens!
        /
        switch(EntityFreshRocket.sideHit)
        {
        case 0: //BOTTOM
        EntityFreshRocket.blockY--;
        break;
        case 1: //TOP
        EntityFreshRocket.blockY++;
        break;
        case 2: //EAST
        EntityFreshRocket.blockZ--;
        break;
        case 3: //WEST
        EntityFreshRocket.blockZ++;
        break;
        case 4: //NORTH
        EntityFreshRocket.blockX--;
        break;
        case 5: //SOUTH
        EntityFreshRocket.blockX++;
        break;
        }
        /
    This method creates the explosion!
        * It uses the entity (Can be null)
        * the three coordinates, the strength
        * and if it should spawn smoke particles
        * around after exploding, the last parameter
        * is if it should set neighboring blocks on fire
        */

    this.worldObj.newExplosion(this, EntityFreshRocket.blockX, EntityFreshRocket.blockY, EntityFreshRocket.blockZ, 20.0F, false, true);
        }

    if (EntityFreshRocket.typeOfHit != MovingObjectPosition.MovingObjectType.MISS)
        {      
            if (EntityFreshRocket.typeOfHit == MovingObjectPosition.MovingObjectType.BLOCK)
            {
            if(EntityFreshRocket.hitInfo == obsidian)
            {
            this.obsidian.breakBlock(worldObj, canBePickedUp, canBePickedUp, canBePickedUp, obsidian, canBePickedUp);
            }
            if(EntityFreshRocket.entityHit != null)
            {
                byte b0 = 0;

    if(EntityFreshRocket.entityHit instanceof EntityBlaze)
                {
                    b0 = 3;
                }

    EntityFreshRocket.entityHit.attackEntityFrom(DamageSource.cactus, distanceWalkedModified);
            }

    for(int i = 0; i < 8; ++i)
            {
                this.worldObj.spawnParticle("largeexplode", this.posX, this.posY, this.posZ, 0.0D, 0.0D, 0.0D);
            }

    if(!this.worldObj.isRemote)

    {
                this.setDead();
            }
        }
        }
        }
    }



  • Ta classe d'entité n'a pas l'air très propre, pourquoi il y a des setSize dans le setThrowableHeading ? Et pourquoi si peux de paramètres sont utilisés ?

    Rajoute des logs dans ta fonction pour faire spawner l'entité pour voir si le problème vient avec les calculs pour faire spawner l'entité ou si le problème vient une fois le spawn fait.



  • Ok je up le post pour mettre à jour mes classes et mes problèmes.

    Problème 1 :
    En changeant quelques trucs dans la classe de l'entité mon projectile n'a plus de render en jeu -_-

    Problème 2 :
    Le projectile ne peut être lancer que vers le nord ou le sud.

    classe de l'envoi du projectile :```java
    package fr.freshblock.freshrocket.common;

    import cpw.mods.fml.relauncher.Side;
    import fr.freshblock.freshrocket.entity.projectile.EntityFreshRocket;
    import net.minecraft.block.Block;
    import net.minecraft.block.BlockDispenser;
    import net.minecraft.client.model.ModelRenderer;
    import net.minecraft.dispenser.BehaviorDefaultDispenseItem;
    import net.minecraft.dispenser.IBlockSource;
    import net.minecraft.dispenser.IPosition;
    import net.minecraft.entity.Entity;
    import net.minecraft.init.Blocks;
    import net.minecraft.item.ItemStack;
    import net.minecraft.util.EnumFacing;
    import net.minecraft.util.Facing;
    import net.minecraft.world.World;

    public final class BehaviorDefault extends BehaviorDefaultDispenseItem
    {
    @Override
    protected ItemStack dispenseStack(IBlockSource source, ItemStack stack)
    {
            //Obtenir le monde

    World world = source.getWorld();

    IPosition iposition = BlockDispenser.func_149939_a(source);
            EnumFacing enumfacing = BlockDispenser.func_149937_b(source.getBlockMetadata());

    //instancier l'entité

    Entity entityfreshrocket = new EntityFreshRocket(world, iposition.getX(), iposition.getY(), iposition.getZ());

    double x = source.getX();
            double x1 = iposition.getX();
            double dirX = x1-x;

    double y = source.getY();
            double y1 = iposition.getY();
            double dirY = y-y1;

    double z = source.getZ();
            double z1 = iposition.getZ();
            double dirZ = z-z1;

    entityfreshrocket.motionX = dirX;
            entityfreshrocket.motionY = dirY;
            entityfreshrocket.motionZ = dirZ;

    world.spawnEntityInWorld(entityfreshrocket);

    –stack.stackSize;
            return stack;
        }
    }
    Classe de l'entité :java
    package fr.freshblock.freshrocket.entity.projectile;

    import java.util.List;

    import cpw.mods.fml.common.registry.EntityRegistry;
    import net.minecraft.block.Block;
    import net.minecraft.entity.Entity;
    import net.minecraft.entity.EntityLivingBase;
    import net.minecraft.entity.IProjectile;
    import net.minecraft.entity.monster.EntityBlaze;
    import net.minecraft.entity.player.EntityPlayer;
    import net.minecraft.entity.projectile.EntityThrowable;
    import net.minecraft.init.Blocks;
    import net.minecraft.nbt.NBTTagCompound;
    import net.minecraft.nbt.NBTTagList;
    import net.minecraft.util.AxisAlignedBB;
    import net.minecraft.util.DamageSource;
    import net.minecraft.util.IProgressUpdate;
    import net.minecraft.util.MathHelper;
    import net.minecraft.util.MovingObjectPosition;
    import net.minecraft.util.Vec3;
    import net.minecraft.util.MovingObjectPosition.MovingObjectType;
    import net.minecraft.world.Explosion;
    import net.minecraft.world.World;

    public class EntityFreshRocket extends Entity
    {
    private int xTile = -1;
        private int yTile = -1;
        private int zTile = -1;
        private Block inTile;
        private int ticksAlive;
        private int inData;
        private boolean inGround; // Dans un bloc ou pas
        public int arrowShake;
        public Entity shootingEntity; // Le joueur qui a tiré le projectile
        private int ticksInGround; // Je pense que c'est clair
        private int ticksInAir; // Je pense que c'est clair également
        private double damage = 6.0D; // Dégats du projectile
        private int knockbackStrength; // Puissance du knockback
        public int canBePickedUp;

    public double accelerationX;
        public double accelerationY;
        public double accelerationZ;

    @Override
    protected void entityInit() 
    {

    }

    @Override
    protected void readEntityFromNBT(NBTTagCompound p_70037_1_) 
    {

    }

    @Override
    protected void writeEntityToNBT(NBTTagCompound p_70014_1_) 
    {

    }
    public void setThrowableHeading(double p_70186_1_, double x, double y, float z, float p_70186_8_)
        {
            this.renderDistanceWeight = 10.0D;
            this.setSize(0.5F, 0.5F);
            this.setPosition(x, y, z);
            this.yOffset = 0.0F;

    }

    public EntityFreshRocket(World worldIn)
        {
            super(worldIn);
            this.renderDistanceWeight = 10.0D; // Si je comprend bien, la distance
                                               // du render de la flèche
            this.setSize(0.5F, 0.5F); // taille du projectile
        }

    public EntityFreshRocket(World worldIn, double x, double y, double z)

    {
            super(worldIn);
            this.renderDistanceWeight = 10.0D; // Pareil qu'au dessus
            this.setSize(0.5F, 0.5F); // Pareil qu'au dessus
            this.setPosition(x, y, z); // La position du projectile
            this.motionX = this.motionY = this.motionZ = 0.0D;
            x += this.rand.nextGaussian() * 0.4D;
            y += this.rand.nextGaussian() * 0.4D;
            z += this.rand.nextGaussian() * 0.4D;
            double d3 = (double)MathHelper.sqrt_double(x * x + y * y + z * z);
            this.accelerationX = x / d3 * 0.1D;
            this.accelerationY = y / d3 * 0.1D;
            this.accelerationZ = z / d3 * 0.1D;
        }

    public EntityFreshRocket(World worldIn, EntityLivingBase shooter, EntityLivingBase p_i1755_3_, float p_i1755_4_, float p_i1755_5_)
        {
            super(worldIn);
            this.renderDistanceWeight = 10.0D; // Toujours pareil
            this.shootingEntity = shooter; // Qui a tiré le projectile

    if(shooter instanceof EntityPlayer)
            {
                this.canBePickedUp = 0; // Si le tireur peut ramasser le projectile
            }
        }

    public EntityFreshRocket(World worldIn, EntityLivingBase shooter, float p_i1756_3_) // Quasiment la mème qu'au dessus
        {
            super(worldIn);
            this.renderDistanceWeight = 10.0D;
            this.shootingEntity = shooter;

    if(shooter instanceof EntityPlayer)
            {
                this.canBePickedUp = 0;
            }
        }

    protected void onImpact(MovingObjectPosition EntityFreshRocket)
        {
        if(EntityFreshRocket.typeOfHit == MovingObjectType.BLOCK)
        {
        switch(EntityFreshRocket.sideHit)
        {
        case 0: //BOTTOM
        EntityFreshRocket.blockY--;
       case 1: //TOP
        EntityFreshRocket.blockY++;
        break;
        case 2: //EAST
        EntityFreshRocket.blockZ--;
        break;
        case 3: //WEST
        EntityFreshRocket.blockZ++;
        break;
        case 4: //NORTH
        EntityFreshRocket.blockX--;
        break;
        case 5: //SOUTH
        EntityFreshRocket.blockX++;
        break;
        }

    this.worldObj.spawnParticle("largeexplode", this.posX, this.posY, this.posZ, 0.0D, 0.0D, 0.0D);
        }
            if(!this.worldObj.isRemote)
            {
        this.worldObj.newExplosion(this, EntityFreshRocket.blockX, EntityFreshRocket.blockY, EntityFreshRocket.blockZ, 2F, false, true);
                this.setDead();
            }

    if (this.ticksInAir == 20 || !this.worldObj.isRemote && (this.shootingEntity != null && this.shootingEntity.isDead || !this.worldObj.blockExists((int)this.posX, (int)this.posY, (int)this.posZ)))
            {
                this.setDead();
            }
            else
            {
                super.onUpdate();

    if (this.inGround)
                {
                    if (this.worldObj.getBlock(arrowShake, arrowShake, arrowShake) == this.inTile)
                    {
                        ++this.ticksAlive;

    if (this.ticksAlive == 20)
                        {
                            this.setDead();
                        }
                        return;
                    }

    this.inGround = false;
                    this.ticksAlive = 0;
                    this.ticksInAir = 0;
                }
                else
                {
                    ++this.ticksInAir;
                }

    Vec3 vec3 = Vec3.createVectorHelper(this.posX, this.posY, this.posZ);
                Vec3 vec31 = Vec3.createVectorHelper(this.posX + this.motionX, this.posY + this.motionY, this.posZ + this.motionZ);
                MovingObjectPosition movingobjectposition = this.worldObj.rayTraceBlocks(vec3, vec31);
                vec3 = Vec3.createVectorHelper(this.posX, this.posY, this.posZ);
                vec31 = Vec3.createVectorHelper(this.posX + this.motionX, this.posY + this.motionY, this.posZ + this.motionZ);

    if (movingobjectposition != null)
                {
                    vec31 = Vec3.createVectorHelper(movingobjectposition.hitVec.xCoord, movingobjectposition.hitVec.yCoord, movingobjectposition.hitVec.zCoord);
                }

    Entity entity = null;
                List list = this.worldObj.getEntitiesWithinAABBExcludingEntity(this, this.boundingBox);
                double d0 = 0.0D;

    for (int i = 0; i < list.size(); ++i)
                {
                    Entity entity1 = (Entity)list.get(i);

    if (entity1.canBeCollidedWith() && (!entity1.isEntityEqual(this.shootingEntity) || this.ticksInAir >= 25))
                    {
                        float f = 0.3F;
                        AxisAlignedBB axisalignedbb = entity1.boundingBox.expand((double)f, (double)f, (double)f);
                        MovingObjectPosition movingobjectposition1 = axisalignedbb.calculateIntercept(vec3, vec31);

    if (movingobjectposition1 != null)
                        {
                            double d1 = vec3.distanceTo(movingobjectposition1.hitVec);

    if (d1 < d0 || d0 == 0.0D)
                            {
                                entity = entity1;
                                d0 = d1;
                            }
                        }
                    }
                }

    if (entity != null)
                {
                    movingobjectposition = new MovingObjectPosition(entity);
                }

    if (movingobjectposition != null)
                {
                    this.onImpact(movingobjectposition);
                }

    this.posX += this.motionX;
                this.posY += this.motionY;
                this.posZ += this.motionZ;

    if (this.isInWater())
                {
                    for (int j = 0; j < 4; ++j)
                    {
                        float f3 = 0.25F;
                        this.worldObj.spawnParticle("bubble", this.posX, this.posY, this.posZ, this.motionX, this.motionY, this.motionZ);
                    }
                }
                this.worldObj.spawnParticle("smoke", this.posX, this.posY + 0.5D, this.posZ, 0.0D, 0.0D, 0.0D);
                this.setPosition(this.posX, this.posY, this.posZ);
            }
            for (int k = 0; k < 10; ++k)
            {
            if (k == 10)
            {
            this.setDead();
            }
            }
        }
     }



  • Up j'ai résolu le problème de direction car si on regarde bien la classe BehaviorDefault aux lignes 41 - 45 les vecteurs y et z étaient inversés x).
    Mais le problème de rendu est toujours d'actualité



  • Je UP le post


  • Administrateurs

    Doucement, c'est 24h avant de up normalement. J'avais même pas vu pour les directions x)
    Je vais regarder pour le rendu cette après-midi.


    Bon, ton code était une vrai horreur.
    J'ai changé pas mal de chose.



  • OK mdr désolé pour le carnage x) MERCI beaucoup robin maintenant j'ai un rendu en jeu!  🙂