Как правильно сломать блок вручную с учётом предмета в руке игрока?

Версия Minecraft
1.12.2
222
5
28
Есть некий плагин на Bukkit, с помощью которого реализована так называемая супер кирка, которая при взаимодействии с блоком ломает его натурально и с учётом эффектов на кирке.
На данный момент я переписываю ряд плагинов для Sponge. На текущей стадии разработки, метод, который помог бы мне сделать это в виде плагина на платформе Sponge ещё не реализован, поэтому я пришёл к выводу, что придётся сделать его модом.

Вот видео с работой мода на данном этапе:
Код:
Java:
    @SubscribeEvent
    public static void interact(PlayerInteractEvent.LeftClickBlock e) {
        if (e.getHand() == EnumHand.MAIN_HAND) {
            EntityPlayer p = e.getEntityPlayer();
            BlockPos pos = e.getPos();
            World world = p.world;
            TileEntity tileEntity = world.getTileEntity(pos);
            IBlockState blockState = world.getBlockState(pos);
            Block block = blockState.getBlock();
            if (block.removedByPlayer(blockState, world, pos, p, true)) {
                block.harvestBlock(world, p, pos, blockState, tileEntity, e.getItemStack());
                p.sendMessage(new TextComponentString("broken?"));
            }
        }
    }

У меня ряд вопросов:
1. Правильно ли подобрано событие для этого?
2. Правильно ли я ломаю блок и создаю дроп после ломания?
3. В документации к методу removedByPlayer есть описание параметру willHarvest (boolean):
Код:
@param willHarvest True if Block.harvestBlock will be called after this, if the return in true.
Can be useful to delay the destruction of tile entities till after harvestBlock
Как правильно понимать это? Имеется ввиду, что метод при значении true сам вызовет метод harvestBlock или то, что я сам вызову этот метод?
Если не вызывать harvestBlock вручную, то блок просто пропадает, но дроп после него не появляется.
 
Последнее редактирование:
Решение
Господи, только дошло.
Возьми лучше PlayerEvent.BreakSpeed и поставь newSpeed в ивенте на другое число(поиграйся, чтобы блок ломался моментально). Ну и конечно же добавь проверки свои.
3,005
192
592
5,018
47
783
через эвент райтклика(лефтклика) по блоку вставляй world.destroyBlock();
Ломает любой блок мгновенно
 
222
5
28
Посмотрите, как вам?
Осталась одна проблема. Нужно вручную отнимать прочность предмета при удачном ломании блока. Подскажите, как это сделать?

Java:
    @SubscribeEvent()
    public static void interact(PlayerInteractEvent.LeftClickBlock e) {
        if (e.getHand() == EnumHand.MAIN_HAND) {
            EntityPlayer p = e.getEntityPlayer();
            if (source.getSuperPickaxeManager().isEnableSpaMode(p)) { //проверяю, что SPA мод включён.
                ItemStack itemStack = e.getItemStack();
                if (source.getSuperPickaxeManager().isRequiredTool(itemStack)) { //проверяю, что пытаются ломать специальным предметом из списка.
                    World world = p.world;
                    BlockPos pos = e.getPos();
                    TileEntity tileEntity = world.getTileEntity(pos);
                    IBlockState state = world.getBlockState(pos);
                    Block block = state.getBlock();
                    if (!source.getSuperPickaxeManager().isBlockedBlock(block)) { //проверяю, что этот блок можно ломать, BEDROCK к примеру под запретом.
                        if (ForgeHooks.canHarvestBlock(block, p, world, pos)) { //Этим проверяю, что игрок может НОРМАЛЬНО добыть блок и получить хоть какой-то дроп.
                            if (block.removedByPlayer(state, world, pos, p, true)) { //если так, то ломаю блок
                                block.harvestBlock(world, p, pos, state, tileEntity, itemStack); // и спавню дроп
                            }
                        } else {
                            block.removedByPlayer(state, world, pos, p, true); //иначе говорю, что блок был сломан в пустую.
                        }
                    }
                }
            }
        }
    }
 
Последнее редактирование:

tox1cozZ

aka Agravaine
8,456
598
2,893
Господи, только дошло.
Возьми лучше PlayerEvent.BreakSpeed и поставь newSpeed в ивенте на другое число(поиграйся, чтобы блок ломался моментально). Ну и конечно же добавь проверки свои.
 
222
5
28
Вот вроде как всё работает идеально, но почему то новой скорости не хватает для обсидиана. Что скажите?
Java:
private static final float NEW_SPEED = 500.0f;
    
    @SubscribeEvent()
    public static void breakSpeed(PlayerEvent.BreakSpeed e) {
        EntityPlayer p = e.getEntityPlayer();
        if (p.swingingHand == EnumHand.MAIN_HAND) {
            if (source.getSuperPickaxeManager().isEnableSpaMode(p)) {
                ItemStack itemStack = p.getHeldItemMainhand();
                if (source.getSuperPickaxeManager().isRequiredTool(itemStack)) {
                    Block block = e.getState().getBlock();
                    if (!source.getSuperPickaxeManager().isBlockedBlock(block)) {
                        e.setNewSpeed(NEW_SPEED);
                    }
                }
            }
        }
    }
 
Сверху