java - 获取静脉中所有相似的 block

标签 java bukkit

我正在尝试将所有类似的 block 放在一起。但我的代码似乎只在 5 x 5 block 半径内获取 block 。

我尝试使用 while 方法

public List<Block> getVein(Block b){
    List<Block> blocks = similarNear(null, b);
    ListIterator<Block> toCheck = blocks.listIterator();
    while(toCheck.hasNext()) {
        Block current = toCheck.next();
        if(!blocks.contains(current))
            blocks.add(current);
        for(Block block : similarNear(blocks, current)) {
            if(!blocks.contains(block))
                toCheck.add(block);
        }
    }
    return blocks;
}

和相似的Near()

    public List<Block> similarNear(List<Block> current, Block block){
    List<Block> blocks = new ArrayList<Block>();
    Material mat = block.getType();
    Location loc = block.getLocation();

    if(loc.clone().add(0, -1, 1).getBlock().getType() == mat)
        blocks.add(loc.clone().add(0, -1, 1).getBlock());
    if(loc.clone().add(0, -1, -1).getBlock().getType() == mat)
        blocks.add(loc.clone().add(0, -1, -1).getBlock());
    if(loc.clone().add(1, -1, 0).getBlock().getType() == mat)
        blocks.add(loc.clone().add(1, -1, 0).getBlock());
    if(loc.clone().add(-1, -1, 0).getBlock().getType() == mat)
        blocks.add(loc.clone().add(-1, -1, 0).getBlock());
    if(loc.clone().add(1, -1, 1).getBlock().getType() == mat)
        blocks.add(loc.clone().add(1, -1, 1).getBlock());
    if(loc.clone().add(-1, -1, -1).getBlock().getType() == mat)
        blocks.add(loc.clone().add(-1, -1, -1).getBlock());
    if(loc.clone().add(-1, -1, 1).getBlock().getType() == mat)
        blocks.add(loc.clone().add(-1, -1, 1).getBlock());
    if(loc.clone().add(1, -1, -1).getBlock().getType() == mat)
        blocks.add(loc.clone().add(1, -1, -1).getBlock());
    if(loc.clone().add(0, -1, 0).getBlock().getType() == mat)
        blocks.add(loc.clone().add(0, -1, 0).getBlock());

    if(loc.clone().add(0, 0, 1).getBlock().getType() == mat)
        blocks.add(loc.clone().add(0, 0, 1).getBlock());
    if(loc.clone().add(0, 0, -1).getBlock().getType() == mat)
        blocks.add(loc.clone().add(0, 0, -1).getBlock());
    if(loc.clone().add(1, 0, 0).getBlock().getType() == mat)
        blocks.add(loc.clone().add(1, 0, 0).getBlock());
    if(loc.clone().add(-1, 0, 0).getBlock().getType() == mat)
        blocks.add(loc.clone().add(-1, 0, 0).getBlock());
    if(loc.clone().add(1, 0, 1).getBlock().getType() == mat)
        blocks.add(loc.clone().add(1, 0, 1).getBlock());
    if(loc.clone().add(-1, 0, -1).getBlock().getType() == mat)
        blocks.add(loc.clone().add(-1, 0, -1).getBlock());
    if(loc.clone().add(-1, 0, 1).getBlock().getType() == mat)
        blocks.add(loc.clone().add(-1, 0, 1).getBlock());
    if(loc.clone().add(1, 0, -1).getBlock().getType() == mat)
        blocks.add(loc.clone().add(1, 0, -1).getBlock());

    if(loc.clone().add(0, 1, 1).getBlock().getType() == mat)
        blocks.add(loc.clone().add(0, 1, 1).getBlock());
    if(loc.clone().add(0, 1, -1).getBlock().getType() == mat)
        blocks.add(loc.clone().add(0, 1, -1).getBlock());
    if(loc.clone().add(1, 1, 0).getBlock().getType() == mat)
        blocks.add(loc.clone().add(1, 1, 0).getBlock());
    if(loc.clone().add(-1, 1, 0).getBlock().getType() == mat)
        blocks.add(loc.clone().add(-1, 1, 0).getBlock());
    if(loc.clone().add(1, 1, 1).getBlock().getType() == mat)
        blocks.add(loc.clone().add(1, 1, 1).getBlock());
    if(loc.clone().add(-1, 1, -1).getBlock().getType() == mat)
        blocks.add(loc.clone().add(-1, 1, -1).getBlock());
    if(loc.clone().add(-1, 1, 1).getBlock().getType() == mat)
        blocks.add(loc.clone().add(-1, 1, 1).getBlock());
    if(loc.clone().add(1, 1, -1).getBlock().getType() == mat)
        blocks.add(loc.clone().add(1, 1, -1).getBlock());
    if(loc.clone().add(0, 1, 0).getBlock().getType() == mat)
        blocks.add(loc.clone().add(0, 1, 0).getBlock());

 // Remove duplicate blocks
    List<Block> filtered = new ArrayList<>();
    for(Block b : blocks) {
        if(current == null) {
            filtered.add(b);
            continue;
        }else {
            if(!current.contains(b)) {
                if(!filtered.contains(b))
                    filtered.add(b);
            }
        }
    }

    return filtered;
}

我还想添加一个上限,比如只允许它打破 25 个区 block ,但我不知道如何添加它而不阻止它在一个方向上找到 25 个区 block ,然后停止(如果这有意义的话)。

最佳答案

在这里,我尝试尽可能地注释代码,任何建议都会受到赞赏。

//Loops around a block to find other blocks that matches with the center (the given block)
private ArrayList<Block> search(Block center) {
    //The maximum amount of blocks to find (the 'cap', our limit)
    final int max = 25;

    ArrayList<Block> blocks = new ArrayList<>();
    Queue<Block> toSearch = new LinkedList<>();

    //Add the center to list, so it has something to start the search
    toSearch.add(center);

    //While we have something to search and have not reached the limit (the 'cap')
    while (toSearch.size() > 0 && blocks.size() < max) {
        Block b = toSearch.remove(); //Get the block on top of the queue, (and remove it)

        blocks.add(b); //Since this block is already of the type we want, we add it the found list (in this case is the 'blocks' var)

        //Find all its neighbours
        for (Block around : findNeighbours(b)) {
            //We do this check here too 'cause findNeighbours() might return up to 26 blocks and it might be too much
            //eg. we have a max of 50 blocks and have already found 45, if findNeighbours find more than five blocks we want to ignore to others
            //that way we stay within our limit, and once this check is made once the whole loop will end
            if (blocks.size() >= max) {
                break;
            }

            //Only add this block if not yet found/processed/searched
            if (toSearch.contains(around) || blocks.contains(around)) {
                continue;
            }

            toSearch.add(around);
        }

        //If in our toSearch list we already enough blocks to fill our limit we stop the search and add as much as we need to fill up out limit.
        //This can save some resources when searching for common blocks like dirt and stone, which we might find a lot and not all of them will be added to our list
        if (toSearch.size() + blocks.size() >= max) {
            int remains = max - blocks.size(); //Gets how many more blocks we need to fulfill our goal (the limit)

            for (int i = 0; i < remains; i++) {
                blocks.add(toSearch.remove());
            }

            break;
        }
    }

    return blocks;
}

//Finds all neighbours around a block
private List<Block> findNeighbours(Block block) {
    //to avoid a bunch of ifs we use these 3 fors to loop over each axis (X, Y, Z)

    ArrayList<Block> blocks = new ArrayList<>();

    //SQUARED 'radius' to search around
    final int searchRadius = 1;

    for (int x = -searchRadius; x <= searchRadius; x++) {
        for (int y = -searchRadius; y <= searchRadius; y++) {
            for (int z = -searchRadius; z <= searchRadius; z++) {
                if (x == 0 && y == 0 && z == 0) {continue;}

                //Get the block at this location (x,y,z)
                Block near = block.getLocation().clone().add(x, y, z).getBlock();

                //Check if the found block is a valid match. eg: is the same type, has the same data/variant
                if (match(near, block)) {
                    blocks.add(near);
                }
            }
        }
    }

    return blocks;
}

//Checks if a matches to b
private boolean match(Block a, Block b) {
    //Checks only the block type, ot its variant/data
    //return a.getType() == b.getType();

    //Checks its type and its data/variant (might not work on all bukkit/spigot versions)
    return a.getType() == b.getType() && a.getState().getData().equals(b.getState().getData());
}

关于java - 获取静脉中所有相似的 block ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51757534/

相关文章:

java - 在 J2EE 应用程序中,什么时候调用监听器?

java - 多态性和动态绑定(bind)

java - Spring 3 MVC中的文件上传-空指针异常

java - 如何通过 bukkit 中的配置添加消息?

java - 从 BungeeCord 发送 PluginMessage 到 SpigotServer

java - Minecraft - Bukkit socket

java - 使用 Eclipse(Android) 奇怪的错误

java - 实现雅可比算法来实现拉普拉斯方程

java - 当需要使用另一个线程时,你应该使用Java的Bukkit实现吗?

javascript - 查询 Minecraft(Bukkit) 服务器 Javascript 自动更新