Jump to content

[Solved] [1.19.3] crash with level::destroyBlockProgress


Recommended Posts

Posted (edited)

I made a AI (goal) that zombie break block.

To show the block breaking, I used `destroyBlockProgress` with reference to `BreakDoorGoal`.

It's fine when there's just one or two zombies, but when I summon multiple zombies, it crashes after a few minutes.

crash log: https://gist.github.com/reasure3/9ec90ab2141968535630c5d72558de79

simple code:

public class SetOrBreakBlockGoal extends Goal {
    protected PathfinderMob mob;
    protected LivingEntity target;
    protected Action action;
    protected int blockInteractTime;
    protected int breakTime;
    protected int lastProgress;
    protected BlockState block;
    protected BlockPos.MutableBlockPos blockPos;  <-- This was a problem. not use MutableBlockPos!!
    protected long lastStuckCheckTime;
    protected Vec3 lastStuckCheckPos;
    protected boolean isStuck;

    public SetOrBreakBlockGoal(PathfinderMob mob) {
        this.mob = mob;
        this.action = Action.NONE;
        this.blockInteractTime = -1;
        this.blockPos = new BlockPos.MutableBlockPos(0, 0, 0);
        this.lastProgress = -1;
        this.lastStuckCheckTime = mob.level.getGameTime();
        this.lastStuckCheckPos = Vec3.ZERO;
        this.isStuck = false;
    }

    @Override
    public boolean canUse() {
        if (mob.level instanceof ServerLevel level) {
            if (MathUtil.getDay(level) >= SpawnConfig.ZOMBIE_SET_OR_BREAK_BLOCLK_DAY.get()) {
                target = mob.getTarget();
                if (!isRightTarget()) return false;
                checkStuck();
                return isStuck;
            }
        }
        return false;
    }

    @Override
    public boolean canContinueToUse() {
        if (action == Action.NONE) return false;
        if (blockInteractTime < 0) return false;
        if (isRightTarget()) {
            return mob.level.getBlockState(blockPos).is(block.getBlock());
        }
        return false;
    }

    @Override
    public void start() {
        int dy = target.getBlockY() - mob.getBlockY();
        if (dy > 1) {
            blockPos.set(mob.getBlockX(), mob.getBlockY() + 2, mob.getBlockZ());
            block = mob.level.getBlockState(blockPos);
            if (block.isAir()) {
                // set block code
            } else {
                block = mob.level.getBlockState(blockPos);
                breakTime = getBlockBreakTick();
               blockInteractTime = breakTime;
               if (breakTime == 0) action = Action.BREAK_INSTANCE;
               else if (breakTime < 0) action = Action.NONE;
               else action = Action.BREAK;
            }
        } else action == Action.NONE;
      
        if (action == Action.BREAK && !ForgeHooks.canEntityDestroy(mob.level, blockPos, mob)) {
            action = Action.NONE;
        }
    }

    @Override
    public void tick() {
        if (action == Action.BREAK) {
            if (mob.level.random.nextInt(10) == 0 && !mob.swinging) {
                mob.swing(mob.getUsedItemHand());
            }
            // breaking block
            int progress = (int) ((float) (breakTime - blockInteractTime) / (float) breakTime * 10.0f);
            if (progress != lastProgress) {
                mob.level.destroyBlockProgress(mob.getId(), blockPos, progress);
                lastProgress = progress;
            }
        }
        // goal is finished
        if (blockInteractTime == 0) {
            if (action == Action.BREAK_INSTANCE || action == Action.BREAK) {
                block = mob.level.getBlockState(blockPos);
                BlockEntity blockEntity = block.hasBlockEntity() ? mob.level.getBlockEntity(blockPos) : null;
                mob.level.removeBlock(blockPos, false);
                // this.mob.level.levelEvent(1021, blockPos, 0);
                this.mob.level.levelEvent(2001, blockPos, Block.getId(mob.level.getBlockState(blockPos)));
                Block.dropResources(block, mob.level, blockPos, blockEntity, mob, mob.getMainHandItem());
            } 
        }
        blockInteractTime--;
    }

    @Override
    public void stop() {
        if (action == Action.BREAK)
           mob.level.destroyBlockProgress(mob.getId(), blockPos, -1);
        action = Action.NONE;
        blockInteractTime = -1;
        lastProgress = -1;
        isStuck = false;
        lastStuckCheckTime = mob.level.getGameTime();
        lastStuckCheckPos = mob.position();
    }
}

full code: https://github.com/reasure3/ZombieSurvivalMod/blob/master/src/main/java/com/reasure/zomsurvival/entity/goal/SetOrBreakBlockGoal.java

Edited by reasure3
Posted

I know the cause. It is solved by using BlockPos instead of MutableBlockPos. I thought it wouldn't matter because it was packet communication from the server to the client, but it seems to be different in single player.

  • reasure3 changed the title to [Solved] [1.19.3] crash with level::destroyBlockProgress

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.