how would I do this

Discussion in 'Plugin Development' started by xize, May 22, 2013.

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

    xize

    Hello,

    I'm wondering how to calculate through each block which is asigned to each other.
    as example I want to know when a player clicks the lowest block at his house it calculates the whole house but not the rest of the enviroment, it seems really hard for me to find this out how to calculate this inside a for loop, I know how to calculate cuboids but I'm not a math guy:p

    I'm very thankfull if someone can help me with this.
     
  2. Offline

    chasechocolate

    This could be fairly hard because you do not know which blocks belong to their house. The best thing I can come up with would be to loop through adjacent blocks (maybe while loop) and check if the type is the same of the type of the block that the player clicked on.
     
  3. Offline

    MrTwiggy

    One potential way you could do it is to have a list of block types that are not considered part of the environment (stonebrick, wooden planks, signs, doors, etc.) Then basically when a player clicks a block, you go to every block on each side, check if it is NOT an environmental block, and if it isn't, then you add that to the list of blocks for the house, and repeat the same thing for that block. So it sort of 'spreads' outwards, incasing the whole house.

    Some major issues with this, however, is if a player builds their house using environmental blocks such as tree logs, leaves, grass, etc.

    Also, if a player has a part of their house that isn't adjacent to another part of their house, it wouldn't be included. A potential solution for this is that once you have all the blocks, get the minimum and maximum vector points, and then just include everything in-between that isn't an environmental block.

    Honestly, the most effective way would be to log/keep track of player-placed blocks in the first place.
     
  4. Offline

    xize

    Thanks for the help, I think best way is to use a sort of blacklist then make a for loop which work as a cuboid but then I will start at the block location and just loop and filter blacklisted blocks like air grass etc

    Code:
    Location loc = block.getLocation();
    Double x = loc.getX();
    Double y = loc.getY();
    Double z = loc.getZ();
    For(int X =0; X < 80;X++) {
        For(int Z=0; Z < 80;Z++) {
             Location loc2 = new Location(x+X, y+Y, z+Z);
             If(!blacklistBoolean(loc2.getBlock())) {
                 //do something
              } else {
                  //do nothing
              }
        }
    }
    
    The code isnt that good tho, and forgot to loop with y, there is no way to check when y is building layers to check if the blocks at x z are all air and interupt the loop?
     
  5. for(int X=0; X<80; X++){
    for(int Y=0; Y<80; Y++){
    for(int Z=0; Z<80; Z++){
    //create new loc and do stuffs
    }
    }
    }

    Or start with one block and go though all the faces to find other blocks connected and mark those as HouseBlocks. Go though a loop of all HouseBlocks to find new, connected blocks (watch out for duplicate blocks) and keep doing that untill the array of HouseBlocks remains the same, because that means no other blocks are attached to the structure. You can then create a cuboid based on the 2 cornerblocks. If you need a code sample just ask for it.

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

    xize

    thanks, this is what ive for now, how ever I'm stuck how to check if the lastest for loop contains air between x and z blocks on y as one layer, I don't like to add a new for loop though that would be pretty heavy for the cpu I guess.

    Code:
    protected static HashSet<Material> blacklist = new HashSet<Material>();
     
    public void setBlacklist() {
      blacklist.add(Material.GRASS);
      blacklist.add(Material.COAL);
      blacklist.add(Material.LEAVES);
      blacklist.add(Material.WATER);
      blacklist.add(Material.STATIONARY_WATER);
      blacklist.add(Material.LAVA);
      blacklist.add(Material.STATIONARY_LAVA);
      blacklist.add(Material.DIRT);
      blacklist.add(Material.GRAVEL);
      blacklist.add(Material.STONE);
      blacklist.add(Material.AIR);
      blacklist.add(Material.SAND);
    }
     
    public boolean blacklist(Block block) {
      for(Material mat : blacklist) {
      if(block.getType() == mat) {
        return false;
      } else {
        return true;
      }
      }
      return false;
    }
     
    public void claimBlocks(Block targetBlock) {
      Location loc = targetBlock.getLocation();
      Double x = loc.getX();
      Double y = loc.getY();
      Double z = loc.getZ();
      int maximum_range = 50;
      for(int X = 0; X < maximum_range;X++) {
      for(int Z = 0; Z < maximum_range; Z++) {
        for(int Y = 0; Y < 100;Y++) {
        Block block = targetBlock.getWorld().getBlockAt(new Location(targetBlock.getWorld(), x+X, y, z+Z));
        if(blacklist(block)) {
          //now need to do a check if the lastest layer is only air, then return exit the method
        } else {
          //do nothing because this is a illegal block!
        }
        }
      }
      }
     
    }
    
     
  7. I think you might want to change the blacklist method a bit. Now if a block is sand, it will return true every single time. Why not change blacklist to an arraylist and use the blacklist.contains(block.getType()) function? Also, in your third loop you might want to do if(!blacklist(block)) as that would make more sense. I am not sure what you mean with need to check if the latest layer is only air, if you could explain that a bit, I might be able to help you.
     
  8. Offline

    xize

    well with the lasted layer I ment when its only contains air so I can do return; to exit the method because I like to start from the bottom of the house and count it per layer up till its only air, however I might experiment later on it:3,
    as for arraylists I'm a bit afraid it would store alot of blocks also perhaps as duplicates, I'm not sure HashSets do the same my server doesn't have much ram so I try to make it not to much memory or cpu consuming:p

    also there is another problem when a player hits as example the bottom layer things which are outside the cuboid like parts of a roof might get ignored, my ideas are to store it into a sql lite database its basicly like a region but I need this when a player adds a friend the player only have to select one block of his house but maybe it is way to much:p

    I whas thinking to make the cuboid a bit bigger, and ignore Material.AIR so ive only the solid blocks to get the full house but without the terrain blocks like gravel, sand, grass etc
     
  9. Offline

    Lucariatias

    Sets make more sense, since the blacklist is unordered and only contains one instance of each material. I agree on using contains() instead of using the loop though, would make far more sense (Set also extends Collection, so has a .contains() method).

    It should be noted that Java is case sensitive, so X is not the same as x. Use x for variables so they don't get confused with classes.

    There is also an else statement that does nothing - just use the single if statement, not every if needs an else!
     
    xize likes this.
  10. Offline

    xize

    hmm, so it filter it automatic out even without the } else { however when the boolean is false?
     
  11. Offline

    Lucariatias

    Yup.
    Code:
    if (condition) {
        //Do something
    }
    
    is exactly the same as doing:
    Code:
    if (condition) {
        //Do something
    } else {
        //Do nothing
    }
    
     
  12. Offline

    xize

    oh that's new for me but pretty usefull though, I thought it would throw a npe but it seems in special cases like in a for loop it doesn't
     
Thread Status:
Not open for further replies.

Share This Page