[Tutorial] Getting blocks in a cube radius

Discussion in 'Spigot Plugin Development' started by antiPerson, May 8, 2015.

  1. So, for http://www.spigotmc.org/wiki/plugin-snippets/ I've decided to make this:

    1. Make a Method
    So first, we will want to make a method to get blocks in a radius, so it will want to look like this:
    Code (Java):
    public ArrayList<Block> getBlocks(Block start, int radius){

    }
    2. Creating an arraylist
    Now, we need somewhere to store all the blocks when we have looped through them. So we will want to create an arraylist.

    Code (Java):
    ArrayList<Block> blocks = new ArrayList<Block>();
    You will want to put this before the 'for' loops. Otherwise, you will be making a new instance of it every time it goes to a new block

    3. Making the 'for' loops
    Now this is the important part. First we will start with the X axis:

    Code (Java):
    for(double x = start.getLocation().getX() - radius; x <= start.getLocation().getX() + radius; x++){

    }
    The radius will be taken from the block that we start from, and then added on to the location, one by one. You will want to do this again for the Y and Z axis. It should look like the example below

    Code (Java):

    for(double x = start.getLocation().getX() - radius; x <= start.getLocation().getX() + radius; x++){
           for(double y = start.getLocation().getY() - radius; y <= start.getLocation().getY() + radius; y++){
             for(double z = start.getLocation().getZ() - radius; z <= start.getLocation().getZ() + radius; z++){
          }
          }
         }
    }
    4. Finishing
    So, now we need to add the block to the ArrayList, so add this inside the last 'for' loop
    [CODE = JAVA]Location loc = new Location(start.getWorld(), x, y, z);
    blocks.add(loc.getBlock());[/CODE = JAVA]

    And finally, at the end of the method, you can return the arraylist of blocks
    Code (Java):
    return blocks;
    5. Final code
    Code (Java):

      public ArrayList<Block> getBlocks(Block start, int radius){
         ArrayList<Block> blocks = new ArrayList<Block>();
         for(double x = start.getLocation().getX() - radius; x <= start.getLocation().getX() + radius; x++){
           for(double y = start.getLocation().getY() - radius; y <= start.getLocation().getY() + radius; y++){
             for(double z = start.getLocation().getZ() - radius; z <= start.getLocation().getZ() + radius; z++){
               Location loc = new Location(start.getWorld(), x, y, z);
               blocks.add(loc.getBlock());
          }
          }
         }
         return blocks;
         }
     
    @jflory7
     
    #1 antiPerson, May 8, 2015
    Last edited: May 9, 2015
    • Useful Useful x 3
    • Like Like x 2
    • Optimistic Optimistic x 1
  2. Inkzzz

    Resource Staff

    This is a very nice, and simple tutorial you've done. Thank you for helping out the community.
     
    • Optimistic Optimistic x 1
  3. So... a tutorial which describes how to create an object (ArrayList) and nest for loops? To what end...? What is it going to teach us? (aside stuff that anyone who even dares to refer to himself as a developer should already know)
     
    • Agree Agree x 6
  4. "Plugin Snippets" aren't really meant for developers in the first place.
     
    • Agree Agree x 2
    • Friendly Friendly x 1
  5. gigosaurus

    Supporter

    Here is what I would do differently.

    Code (Java):
    public List<Block> getBlocks(Block start, int radius){
        if (radius < 0) {
            return new ArrayList<Block>(0);
        }
        int iterations = (radius * 2) + 1;
        List<Block> blocks = new ArrayList<Block>(iterations * iterations * iterations);
        for (int x = -radius; x <= radius; x++) {
            for (int y = -radius; y <= radius; y++) {
                for (int z = -radius; z <= radius; z++) {
                    blocks.add(start.getRelative(x, y, z));
                }
            }
        }
        return blocks;
    }
    Main points:

    Use [code=java][/code] around your code. Looks nicer.
    Use Block.getRelative(int, int, int). So much easier.
    Indent your code.

    Every other change I made was just me being extremely picky and pedantic, making the method as efficient as possible, and imagining that some idiot could put a negative or large radius in there.
     
    #5 gigosaurus, May 9, 2015
    Last edited: May 9, 2015
    • Like Like x 1
    • Agree Agree x 1
  6. Your spaces are inconsistent. Put spaces after 'for' as well and before your curly brackets.

    EDIT: This is for the OP as well.
     
  7. gigosaurus

    Supporter

    Oops, didn't notice that. I just copy and pasted the OP's code and edited it.
     
  8. @gigisaurus code is cleaner and more efficient, but more difficult to understand...

    - Don't use doubles, pretty useless if there aren't floating point numbers

    - Another thing: Does a tutorial / snippet really needs explanation of how to create a method and an object? How to add an Object to an ArrayList? That you have to use return? If somebody doesn't know that, they MUST learn more about (java) programming, before making any plugin.
     
    • Agree Agree x 1
  9. if you know the number of elements (blocks), use an Array... other operation using an array would be much faster.
    however, if you're going to search cubic region and select certain elements (blocks) based on some condition, yes, it's fine to use List/Set to dynamically add elements.

    @gigosaurus's code would be preferable because you don't do extra arithmetic operation in for's condition. (although this part could easily be optimised by the compiler or runtime optimisation).

    for the negative radius check. I would force converting it to a positive value with radius *= -1 or Math.abs(radius). Because radius is conceptually >= 0. so if you specify - radius, the starting point would be the opposite form when you specify radius. but your algorithm still should return the same set of block within the cubic region.
     
    • Agree Agree x 1