Ловлю stackoverflowerror

Версия Minecraft
1.12.2
API
Forge
Имею экскаватор, который должен копать площадь 3х3. При вскапываний блока клиент вылетает и на выходе стаковерлоуеррор...

Java:
@Override
    public boolean onBlockDestroyed(ItemStack stack, World worldIn, IBlockState state, BlockPos pos, EntityLivingBase entityLiving) {
        if(entityLiving instanceof EntityPlayer) {
            for (int i = 0; i < 3; i++) {
                for (int j = 0; j < 3; j++) {
                    for (int k = 0; k < 3; k++) {
                        if(i == 1 && j == 1 && k == 1) continue;
                        breakExtraBlock(stack, worldIn, (EntityPlayer) entityLiving, pos.add(i, j, k)); // Break the block
                    }
                }
            }
        }

        return false;
    }

    public static boolean breakExtraBlock(ItemStack stack, World world, EntityPlayer player, BlockPos pos) {
        IBlockState state = world.getBlockState(pos);
        Block block = state.getBlock();

        if (player.capabilities.isCreativeMode) {
            if (block.removedByPlayer(state, world, pos, player, false)) {
                block.onPlayerDestroy(world, pos, state);
            }

            // send update to client
            if (!world.isRemote) {
                ((EntityPlayerMP) player).connection.sendPacket(new SPacketBlockChange(world, pos));
            }
            return true;
        }

        // callback to the tool the player uses. Called on both sides. This damages the tool n stuff.
        stack.onBlockDestroyed(world, state, pos, player);

        // server sided handling
        if (!world.isRemote) {
            // send the blockbreak event
            int xp = ForgeHooks.onBlockBreakEvent(world, ((EntityPlayerMP) player).interactionManager.getGameType(), (EntityPlayerMP) player, pos);
            if (xp == -1) return false;

            TileEntity tileEntity = world.getTileEntity(pos);
            if (block.removedByPlayer(state, world, pos, player, true)) { // boolean is if block can be harvested, checked above
                block.onPlayerDestroy(world, pos, state);
                block.harvestBlock(world, player, pos, state, tileEntity, stack);
                block.dropXpOnBlockBreak(world, pos, xp);
            }

            // always send block update to client
            ((EntityPlayerMP) player).connection.sendPacket(new SPacketBlockChange(world, pos));
            return true;
        }
        // client sided handling
        else {
            // clientside we do a "this block has been clicked on long enough to be broken" call. This should not send any new packets
            // the code above, executed on the server, sends a block-updates that give us the correct state of the block we destroy.

            // following code can be found in PlayerControllerMP.onPlayerDestroyBlock
            world.playEvent(2001, pos, Block.getStateId(state));
            if (block.removedByPlayer(state, world, pos, player, true)) {
                ((Block) block).onPlayerDestroy(world, pos, state);
            }
            // callback to the tool
            stack.onBlockDestroyed(world, state, pos, player);

            // send an update to the server, so we get an update back
            sendBreakPacket(pos);
            return true;

        }
    }

    public static void sendBreakPacket(BlockPos pos) {
        NetHandlerPlayClient netHandlerPlayClient = Minecraft.getMinecraft().getConnection();
        assert netHandlerPlayClient != null;
        netHandlerPlayClient.sendPacket(new CPacketPlayerDigging(CPacketPlayerDigging.Action.STOP_DESTROY_BLOCK, pos, Minecraft
                .getMinecraft().objectMouseOver.sideHit));
    }

}
Screenshot_2.png
 
Решение
Подожди, я вообще не понял нафига ты сколько накопировал, можно же просто что-то типа world.destroyBlock (или как он там называется) вызвать и всё, тут пакеты какие-то, обработка клиента-сервера, кошмар

Но в любом случае, как я писал выше, рекурсия такого типа (в обработчике события делаем что-то что вызывает это-же событие) решается флагом
onBlockDestroyed -> breakBlock -> onBlockDestroyed -> breakBlock -> ...

Чинится флагом:
Java:
boolean lock = false;

void onBlockDestroyed() {
    if (lock) return;
    lock = true;
    ...breakBlocks
    lock = false;
}
 
Ну я прочитал-таки что за код накопированный, в твоём случае можно просто убрать эту строчку:
Java:
// callback to the tool the player uses. Called on both sides. This damages the tool n stuff.
stack.onBlockDestroyed(world, state, pos, player);
 
Подожди, я вообще не понял нафига ты сколько накопировал, можно же просто что-то типа world.destroyBlock (или как он там называется) вызвать и всё, тут пакеты какие-то, обработка клиента-сервера, кошмар

Но в любом случае, как я писал выше, рекурсия такого типа (в обработчике события делаем что-то что вызывает это-же событие) решается флагом
 
Назад
Сверху