Как сделать задержку перед выстрелом у моба

Версия Minecraft
1.12.2
API
Forge
37
1
3
Есть у меня моб, он летает и стреляет. Хочу перед выстрелом делать задержку на 2 секунды, чтобы проигрывать некий звук. Но получается лишь проигрывать звук во время выстрела. Сам снаряд наследует снежок. Пробовал в методе attackEntityWithRangedAttack проигрывать звук, потом вызывать Thread.sleep(2000) и потом делать выстрел. Но проблема в том, что моб на это время полностью замирает, не может попасть в игрока и натыкается на свои-же снаряды.
Класс моба:
public class EntityCustomBlaze extends EntityMob implements IRangedAttackMob, IMob {
    private float heightOffset = 0.5F;
    private int heightOffsetUpdateTime;

    public EntityCustomBlaze(World world) {
        super(world);
        setSize(1F, 2F);
        this.navigator = new PathNavigateFlying(this, this.world);
        this.moveHelper = new GhastLikeMoveHelper(this);
    }


    @Override
    protected void applyEntityAttributes() {
        super.applyEntityAttributes();
        this.getEntityAttribute(SharedMonsterAttributes.ARMOR).setBaseValue(0D);
        this.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).setBaseValue(0.5D);
        this.getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).setBaseValue(10D);
        this.getEntityAttribute(SharedMonsterAttributes.ATTACK_DAMAGE).setBaseValue(1D);
        this.getEntityAttribute(SharedMonsterAttributes.FOLLOW_RANGE).setBaseValue(48.0D);
       this.getAttributeMap().registerAttribute(SharedMonsterAttributes.FLYING_SPEED);
        this.getEntityAttribute(SharedMonsterAttributes.FLYING_SPEED).setBaseValue(0.5D);
    }

    @Override
    protected void initEntityAI() {
        super.initEntityAI();

        this.tasks.addTask(5, new AiRandomFly(this));
        this.tasks.addTask(7, new AiLookArround(this));
        this.tasks.addTask(6, new EntityAIAttackRanged(this, 1.25D, 15, 20.0F));
        this.targetTasks.addTask(1, new EntityAIFindEntityNearestPlayer(this));
    }

    @Override
    public void onLivingUpdate() {
        super.onLivingUpdate();

        if (!this.world.isRemote) {
            this.setAttackTarget(this.world.getNearestAttackablePlayer(this, 22.0D, 22.0D));
            if(this.world.getDifficulty() == EnumDifficulty.PEACEFUL) {
                this.setDead();
            }
        }
    }

    public void attackEntityWithRangedAttack(EntityLivingBase target, float flval) {

        EntityArrowCustom entityarrow = new EntityArrowCustom(this.world, this);
        double d0 = target.posY + (double)target.getEyeHeight() - 1.100000023841858D;
        double d1 = target.posX - this.posX;
        double d2 = d0 - entityarrow.posY;
        double d3 = target.posZ - this.posZ;
        float f = MathHelper.sqrt(d1 * d1 + d3 * d3) * 0.2F;
        entityarrow.shoot(d1, d2 +(double)f, d3, 2F, 1.0F);
        this.playSound(ModSounds.fire_shoot_sound, 1.0F, 1.0F / (this.getRNG().nextFloat() * 0.4F + 0.8F));
        this.world.spawnEntity(entityarrow);
    }

    @Override
    public void onUpdate() {
        super.onUpdate();
        this.setNoGravity(true);
    }

    @Override
    protected void updateAITasks() {
        if (this.isWet()) {
            this.attackEntityFrom(DamageSource.DROWN, 1.0F);
        }

        --this.heightOffsetUpdateTime;
        if (this.heightOffsetUpdateTime <= 0) {
            this.heightOffsetUpdateTime = 100;
            this.heightOffset = 0.5F + (float)this.rand.nextGaussian() * 3.0F;
        }
        super.updateAITasks();
    }

    @Override
    public void setSwingingArms(boolean swingingArms) {
    }

    public float getEyeHeight() {
        return 1.7F;
    }

    public static class EntityArrowCustom extends EntitySnowball {
        public EntityLivingBase shootingEntity;
        public int ShootDamage = 1;
        public EntityArrowCustom(World a) { super(a); }

        public EntityArrowCustom(World worldIn, double x, double y, double z) {
            super(worldIn, x, y, z);
        }

        public EntityArrowCustom(World worldIn, EntityLivingBase shooter) {
            super(worldIn, shooter);
        }

        @Override
        protected void onImpact(RayTraceResult result) {
            if (result.entityHit != null) {
                if ((result.entityHit instanceof EntityLiving) && !(result.entityHit instanceof EntityCustomBlaze))
                    ((EntityLiving) result.entityHit).addPotionEffect(new PotionEffect(Potion.getPotionById(2), 200, 3));
                result.entityHit.attackEntityFrom(DamageSource.causeThrownDamage(this, this.getThrower()), (float) ShootDamage);

                if (result.entityHit instanceof EntityPlayer) { //Если моб попал в игрока, то игрок телепортируется
                    EntityPlayer player = Minecraft.getMinecraft().player;
                    for (int i = 0; i < 16; ++i) {
                        double X = player.posX + (player.getRNG().nextDouble() - 0.5D) * 8.0D;
                        double Z = player.posZ + (player.getRNG().nextDouble() - 0.5D) * 8.0D;
                        player.setPosition(X, player.posY, Z);
                    }
                }
            }
        }
        @Override
        @SideOnly(Side.CLIENT)
        public void onUpdate() {
            if (this.world.isRemote || (this.shootingEntity == null || !this.shootingEntity.isDead) && this.world.isBlockLoaded(new BlockPos(this))) {
                super.onUpdate();
                this.world.spawnParticle(EnumParticleTypes.SMOKE_LARGE, posX, posY + 0.5D, posZ, 0.0D, 0.0D, 0.0D, new int[0]);
                this.world.spawnParticle(EnumParticleTypes.FLAME, posX, posY + 0.5D, posZ, 0.0D, 0.0D, 0.0D, new int[0]);
            }
        }
    }
}
 
Решение
Можно подробнее про это?
Ну вот есть у тя какой-нить
Java:
tick(){
    //do it!   
}
А ты хочешь, чтобы не каждый тик, а каждые n тиков
Если вставить sleep перед do it, то текущий тик зависнет, отложится вся игра, а не только твое do it.
Поэтому надо пропускать тики примерно так:
Java:
int ticksCount = 0

tick(){
    if(ticksCount==n){
        //do it!
        ticksCount=0;
    }else
        ticksCount++;
}
7,099
324
1,510
Если так сделаешь - зависнет чуть меньше, чем вся игра
Задержки нужно делать путем пропуска тиков в своем обработчике

Метод attackEntityWithRangedAttack вызывается из EntityAIAttackRanged? Если да, то можно сделать свою реализацию EntityAIAttackRanged, добавив в нее задержку перед выстрелом
 
37
1
3
Задержки нужно делать путем пропуска тиков в своем обработчике
Можно подробнее про это? Или ссылку какую-нибудь?


Метод attackEntityWithRangedAttackвызывается из EntityAIAttackRanged? Если да, то можно сделать свою реализацию EntityAIAttackRanged, добавив в нее задержку перед выстрелом
Да, вызывается из EntityAIAttackRanged
 
7,099
324
1,510
Можно подробнее про это?
Ну вот есть у тя какой-нить
Java:
tick(){
    //do it!   
}
А ты хочешь, чтобы не каждый тик, а каждые n тиков
Если вставить sleep перед do it, то текущий тик зависнет, отложится вся игра, а не только твое do it.
Поэтому надо пропускать тики примерно так:
Java:
int ticksCount = 0

tick(){
    if(ticksCount==n){
        //do it!
        ticksCount=0;
    }else
        ticksCount++;
}
 
7,099
324
1,510
Разберись в том, как работает EntityAIAttackRanged. Тогда поймешь ,какие правки нужно будет внести, чтобы была задержка перед запуском снаряда
 
Сверху