Posted January 4, 20232 yr 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 January 4, 20232 yr by reasure3
January 4, 20232 yr 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?
January 4, 20232 yr Author Crash occurs even when the block is a flat block (dirt, sand, etc.). Edited January 4, 20232 yr by reasure3
January 4, 20232 yr 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.
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.