Looping through blocks in a radius

Discussion in 'Plugin Development' started by Captain Dory, Feb 23, 2014.

Thread Status:
Not open for further replies.
  1. Offline

    Captain Dory

    Hai,

    I'm making a mini survival games plugin for someone and I need to get all chests within a sphere (But cube could work) and do stuff with them. I don't know how to do this, so any help would be appreciated :)
     
  2. Offline

    tamajpm

    You can use this. It returns all blocks in a world between two locations:
    Code:java
    1. public List<Block> getRegionBlocks(World world, Location loc1, Location loc2) {
    2. List<Block> blocks = new ArrayList<Block>();
    3.  
    4. for(double x = loc1.getX(); x <= loc2.getX(); x++) {
    5. for(double y = loc1.getY(); y <= loc2.getY(); y++) {
    6. for(double z = loc1.getZ(); z <= loc2.getZ(); z++) {
    7. Location loc = new Location(world, x, y, z);
    8. blocks.add(loc.getBlock());
    9. }
    10. }
    11. }
    12.  
    13. return blocks;
    14. }


    After you get all the blocks with this you need to do something like:
    Code:java
    1. public void fillChests(World world, Location loc1, Location loc2) {
    2. List<Block> blocks = getRegionBlocks(world, loc1, loc2);
    3.  
    4. for(Block block : blocks) {
    5. if(block.getType().equals(Material.CHEST)) {
    6. //Do something.
    7. }
    8. }
    9. }
     
    RafaelEstevamReis likes this.
  3. You can try do a loop around player, will be a Cube, then calculate distance to make it Sphere.

    Within the loop, you can test what is the type of each block.
    But i think there be a better way. I read once something in entity realted with Near [something].

    Be careful with large areas, things can go slow.

    Something like that. (i write by my mind, check it before use!)
    Code:java
    1. Location loc= player.getLocation();
    2. ...
    3. for(int x = loc.getX() - radius; x < loc.getx + radius; x++ )
    4. {
    5. for(int y = loc.getY() - radius; y < loc.getY + radius; y++ )
    6. {
    7. for(int z = loc.getZ() - radius; z < loc.getZ + radius; z++ )
    8. {
    9. //Block b = get block at (x,y,z)
    10. // is this a chest ?
    11. }
    12. }
    13. }
     
  4. Offline

    Captain Dory

    Thanks, this code doesn't seem to be working. It's probably something on my side, this is my code:
    (I have the getRegionBlocks exactly same as one posted)
    Code:java
    1. public void fillChests(World world, Location loc1, Location loc2) {
    2.  
    3. List<Block> blocks = getRegionBlocks(world, loc1, loc2);
    4.  
    5. for(Block block : blocks) {
    6.  
    7. if(block.getType().equals(Material.CHEST)) {
    8.  
    9. for (Player p : Bukkit.getOnlinePlayers()) {
    10.  
    11. p.sendMessage("New chest");
    12.  
    13. }
    14.  
    15. }
    16.  
    17. }
    18.  
    19. }

    My command:
    Code:java
    1.  
    2. @Override
    3. public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args ) {
    4.  
    5. Player p = (Player) sender;
    6.  
    7. if (label.equalsIgnoreCase("ch3st")) {
    8.  
    9. fillChests(Bukkit.getWorld("world"), new Location(Bukkit.getWorld("world"), 0, 100, 0), new Location(Bukkit.getWorld("world"), 50, 0, 50));
    10.  
    11. }
    12.  
    13. return false;
    14.  
    15. }

    It doesn't say 'new Chest' even though there is a chest in that region. Any help appreciated, thanks :)
     
  5. Offline

    tamajpm

    I will make the command and check if it works for me.
     
  6. Offline

    Captain Dory

    Ok thanks :)

    Shameless bump ;)

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 6, 2016
  7. Offline

    tamajpm

    It doesn't work for me to.​
     
  8. Offline

    belven000

    Ok it's the loop that's broken. It returns the same point, both p1 and p2. I'll try and fix it.

    I've tried a few things and all I can get working is this, not really what you want but it gets blocks south east from where you're standing in a square:

    Code:java
    1. private static List<Block> getArenaBlocks(Location l, int radius)
    2. {
    3. World w = l.getWorld();
    4. int xCoord = (int) l.getX();
    5. int zCoord = (int) l.getZ();
    6. int YCoord = (int) l.getY();
    7.  
    8. List<Block> tempList = new ArrayList<Block>();
    9. for (int x = 0; x <= 2 * radius; x++)
    10. {
    11. for (int z = 0; z <= 2 * radius; z++)
    12. {
    13. for (int y = 0; y <= 2 * radius; y++)
    14. {
    15. tempList.add(w.getBlockAt(xCoord + x, YCoord + y, zCoord
    16. + z));
    17. }
    18. }
    19. }
    20. return tempList;
    21. }


    Hope this helps :)

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 6, 2016
  9. Offline

    Captain Dory

    I'll try this tonight :)
     
  10. Offline

    Voltex

    Did you ever make a fix of tamajpm's code? I need it and can't figure out what's wrong with it :p
     
  11. Offline

    GameplayJDK

    Voltex What errors do you get?

    To get all blocks around a location (a central one):
    Code:java
    1.  
    2. private static List<Location> getArenaBlocks(Location l, int radius)
    3. {
    4. World w = l.getWorld();
    5. int xCoord = (int) l.getX();
    6. int zCoord = (int) l.getZ();
    7. int YCoord = (int) l.getY();
    8.  
    9. List<Location> tempList = new ArrayList<Location>();
    10. for (int x = -radius; x <= radius; x++)
    11. {
    12. for (int z = -radius; z <= radius; z++)
    13. {
    14. for (int y = -radius; y <= radius; y++)
    15. {
    16. tempList.add(new Location(w, xCoord + x, YCoord + y, zCoord + z));
    17. }
    18. }
    19. }
    20. return tempList;
    21. }
    22.  

    That should do the thing. It returns a
     
  12. Offline

    Voltex

    Worked this out a bit ago, but this looks more efficient. Thanks :)
     
  13. Offline

    GameplayJDK

    Voltex
    You're welcome :D
    I think there is a way of doing this in an exact sphere, but I prefer not messing around with Math.* Methods
     
  14. Offline

    Voltex

    Neither, 3D geometry scares me (Plus i'm still a few years short of learning it)
     
  15. Offline

    GameplayJDK

    Yes, 3D geometry isn't fun, but 3D cubes are the easiest type, spheres are not so... funny :p
     
  16. Offline

    Loogeh

    Someone else wrote this method and I haven't tested it but it might work.

    Code:
        public List<Location> getSphere(Location loc, int r, int h, boolean hollow, boolean sphere, int plus_y) {
            List<Location> circleblocks = new ArrayList<Location>();
            int cx = loc.getBlockX();
            int cy = loc.getBlockY();
            int cz = loc.getBlockZ();
            for (int x = cx - r; x <= cx + r; x++) {
                for (int z = cz - r; z <= cz + r; z++) {
                    for (int y = (sphere ? cy - r : cy); y < (sphere ? cy + r : cy + h); y++) {
                        double dist = (cx - x) * (cx - x) + (cz - z) * (cz - z) + (sphere ? (cy - y) * (cy - y) : 0);
                        if (dist < r * r && !(hollow && dist < (r - 1) * (r - 1))) {
                            Location l = new Location(loc.getWorld(), x, y + plus_y, z);
                            circleblocks.add(l);
                        }
                    }
                }
            }
            return circleblocks;
        }
     
  17. Offline

    GameplayJDK

    Ultracrepadarian likes this.
Thread Status:
Not open for further replies.

Share This Page