1. Вы находитесь в сообществе Rubukkit. Мы - администраторы серверов Minecraft, разрабатываем собственные плагины и переводим на различные языки плагины наших коллег из других стран.
    Скрыть объявление
Скрыть объявление
В преддверии глобального обновления, мы проводим исследования, которые помогут нам сделать опыт пользования форумом ещё удобнее. Помогите нам, примите участие!

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

Тема в разделе "Разработка плагинов для новичков", создана пользователем therimuru_, 22 июл 2024.

Статус темы:
Закрыта.
  1. Автор темы
    therimuru_

    therimuru_ Активный участник Пользователь

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

    CioLay Активный участник Пользователь

    Баллы:
    61
    Имя в Minecraft:
    NordNM
    Можно реализовать это с помощью рекурсивного метода, который вызывает сам себя для каждого соседнего блока по всем направлениям.

    Вот небольшой концепт:
    Код:
    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;
        }
    }
    
    
    }
     
    Последнее редактирование: 22 июл 2024
  3. Dymeth

    Dymeth Активный участник Пользователь

    Баллы:
    98
    Имя в Minecraft:
    Dymeth
    Майнкрафт НЕ хранит информацию о том, к какому дереву принадлежит тот или иной блок листвы. Можно лишь определить, поставлен блок вручную или сгенерирован. Также можно получить расстояние до ближайшего ствола. Однако в сгенерированном мире не существует даже такого понятия как "дерево". Есть лишь несколько блоков брёвен, которые на уровне данных между собой никак не связаны (например, существуют диагональные ветки).

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

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

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

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

    alexandrage Старожил Пользователь

    Баллы:
    173
    Да помню такие плагины, лучше такое вообще не юзать, ибо по нормальному отделить дерево стоящее рядом и от поставленных бревен игроком невозможно, максимум стату листвы чекнуть можно и все.
     
Статус темы:
Закрыта.

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