Jump to content
View in the app

A better way to browse. Learn more.

Forge Forums

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

Featured Replies

Posted

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

  • Author

A number of cases seem to occur if the block is fluid.
Is there any correct way to check that a block is fluid?

  • Author

Crash occurs even when the block is a flat block (dirt, sand, etc.).

Edited by reasure3

  • Author

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...

Important Information

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

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.