Войти или зарегистрироваться
  • Вы находитесь в сообществе Rubukkit. Мы - администраторы серверов Minecraft, разрабатываем собственные плагины и переводим на различные языки плагины наших коллег из других стран.

Помогите Получение координат всех блоков дерева

Статус
Закрыто для дальнейших ответов.

therimuru_

Активный участник
Пользователь
Баллы
66
Имя в Minecraft
therimuru_
Приветствую. Я пишу плагин, где мне нужно после срубания блока дерева игроком, пропадало сразу всё дерево, вместе с листвой, а через некоторое время дерево обратно восстанавливалось. Как мне, с помощью BlockBreakEvent получить список координат каждого блока дерева? Есть в Bukkit API какие либо инструменты для этого? Или нужно свои скрипты какие-то писать. У меня есть конечно определенная идея, но она сложна в реализации. Хочу узнать ваши варианты. Спасибо.
 
Можно реализовать это с помощью рекурсивного метода, который вызывает сам себя для каждого соседнего блока по всем направлениям.

Вот небольшой концепт:
Код:
private final BlockFace[] adjacentFaces = {
    BlockFace.UP, BlockFace.DOWN,
    BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST, BlockFace.WEST,
    BlockFace.NORTH_EAST, BlockFace.NORTH_WEST, BlockFace.SOUTH_EAST, BlockFace.SOUTH_WEST
};


  @EventHandler
    public void onBlockBreak(BlockBreakEvent event) {
        Block block = event.getBlock();
        if (isLog(block.getType())) {
            Map<Block, Material> treeBlocks = findTreeBlocks(block);


            // Если нужно, вывод списка координат блоков дерева
            List<String> coordinates = getTreeBlockCoordinates(treeBlocks);
            for (String coord : coordinates) {
                System.out.println(coord)
            }


            removeTreeBlocks(treeBlocks);

            new BukkitRunnable() {
                @Override
                public void run() {
                    restoreTreeBlocks(treeBlocks);
                }
            }.runTaskLater(this, 20L * 10); // реснуть через 10 сек допустим...
        }
    }

    private boolean isLog(Material material) {
        return Tag.LOGS.isTagged(material);
    }

    private boolean isLeaf(Material material) {
        return Tag.LEAVES.isTagged(material);
    }

    private Map<Block, Material> findTreeBlocks(Block startBlock) {
        Map<Block, Material> result = new HashMap<>();
        Set<Block> visited = new HashSet<>();
        exploreTree(startBlock, result, visited);
        return result;
    }

// Рекурсивный метод для обхода дерева и листвы
  private void exploreTree(Block block, Map<Block, Material> result, Set<Block> visited) {
        if (!visited.contains(block) && (isLog(block.getType()) || isLeaf(block.getType()))) {
            visited.add(block);
            result.put(block, block.getType());

            for (BlockFace face : adjacentFaces) {
                Block adjacentBlock = block.getRelative(face);
                exploreTree(adjacentBlock, result, visited);

                Block adjacentBlockTwoSteps = adjacentBlock.getRelative(face);
                exploreTree(adjacentBlockTwoSteps, result, visited);
            }
        }
    }

    private void removeTreeBlocks(Map<Block, Material> treeBlocks) {
        for (Block block : treeBlocks.keySet()) {
            block.setType(Material.AIR);
        }
    }

    private void restoreTreeBlocks(Map<Block, Material> treeBlocks) {
        for (Map.Entry<Block, Material> entry : treeBlocks.entrySet()) {
            Block block = entry.getKey();
            Material material = entry.getValue();
            block.setType(material);
        }
    }

  // Если нужно, получение списка координат блоков дерева
    private List<String> getTreeBlockCoordinates(Map<Block, Material> treeBlocks) {
        List<String> coordinates = new ArrayList<>();
        for (Block block : treeBlocks.keySet()) {
            String coord = "X: " + block.getX() + " Y: " + block.getY() + " Z: " + block.getZ();
            coordinates.add(coord);
        }
        return coordinates;
    }
}


}
 
Последнее редактирование:
Приветствую. Я пишу плагин, где мне нужно после срубания блока дерева игроком, пропадало сразу всё дерево, вместе с листвой, а через некоторое время дерево обратно восстанавливалось. Как мне, с помощью BlockBreakEvent получить список координат каждого блока дерева? Есть в Bukkit API какие либо инструменты для этого? Или нужно свои скрипты какие-то писать. У меня есть конечно определенная идея, но она сложна в реализации. Хочу узнать ваши варианты. Спасибо.
Майнкрафт НЕ хранит информацию о том, к какому дереву принадлежит тот или иной блок листвы. Можно лишь определить, поставлен блок вручную или сгенерирован. Также можно получить расстояние до ближайшего ствола. Однако в сгенерированном мире не существует даже такого понятия как "дерево". Есть лишь несколько блоков брёвен, которые на уровне данных между собой никак не связаны (например, существуют диагональные ветки).

В связи с этим к тебе вопрос - как ты будешь определять, к какому блоку относится листва, если два дерева заспаунились рядом? И как ты будешь определять, какое бревно относится к какому стволу?
Собственно, в этом и заключается основная проблема твоей идеи.
Я однажды рекурсивным методом весь лес из тёмного дуба срубил одним ударом...

Короче говоря, тут нужно задать какой-то максимальный радиус листвы от ствола. Чуть проще будет просто добавить лимит на кол-во разрушаемых блоков листвы, но и работать будет более криво.

Ещё можно скопировать ванильный алгоритм определения веток, которые должны упасть. В этом случае всё должно работать идеально с точки зрения пользователя. Но алгоритм этот рекурсивный, поэтому надо быть максимально аккуратным.

Ещё чтобы не запариваться с реализацией - можно найти готовые аналоги плагинов с таким же функционалом и просто использовать их или позаимствовать их код. Так выйдет решить задачу быстрее, но и опыта получишь меньше
 
Последнее редактирование:
Да помню такие плагины, лучше такое вообще не юзать, ибо по нормальному отделить дерево стоящее рядом и от поставленных бревен игроком невозможно, максимум стату листвы чекнуть можно и все.
 
Статус
Закрыто для дальнейших ответов.

Поделиться этой страницей

Назад
Верх