Moving Blocks Problem

Discussion in 'Plugin Development' started by MrGriefer_, Sep 25, 2019.

  1. Offline

    MrGriefer_

    Hello,

    I'm trying to do something like the mini-game Hole In The Wall, and I managed to move an entire wall like shown here:
    Moving Wall (open)
    [​IMG]


    But whenever I set couple of blocks to air, like this:
    Image (open)
    [​IMG]


    and try to move the wall it will just fill all the air blocks and move the wall. What can I do in order to move the wall with the holes?

    Another problem I'm facing is whenever I build the wall facing south or north and start moving the wall it'll start moving sideways like this:
    Moving Sideways (open)
    [​IMG]
     
  2. Offline

    timtower Moderator Moderator

    @MrGriefer_ You need to store which blocks are set and which are not, then rebuild the wall based on that information.
    And for the moving: why not use the players facing direction to set the movement direction?
     
  3. Offline

    MrGriefer_

    Okay so whenever I try to start the moving animation I set the holes and then I stored the holes location in a Set<Block>, but when moving the wall to the next new location and and setting the new location to the old holes blocks and it doesn't seem to work.
    Code (open)

    PHP:
    private Set<BlockairBlocks = new HashSet<>();

    private 
    void start() {
        
    int minX plugin.getConfig().getInt("Wall.Min.X");
        
    int minY plugin.getConfig().getInt("Wall.Min.Y");
        
    int minZ plugin.getConfig().getInt("Wall.Min.Z");
                     
        
    int maxX plugin.getConfig().getInt("Wall.Max.X");
        
    int maxY plugin.getConfig().getInt("Wall.Max.Y");
        
    int maxZ plugin.getConfig().getInt("Wall.Max.Z");
                     
        
    //..
                     
        
    for (int i 04i++) {
            
    int x = (int) (maxX Math.round(Math.random() * (minX maxX)));
            
    int y = (int) (maxY Math.round(Math.random() * (minY maxY)));
            
    int z = (int) (maxZ Math.round(Math.random() * (minZ maxZ)));
            
    Location airBlock = new Location(player.getWorld(), xyz);
            
    airBlock.getBlock().setType(Material.AIR);
            
    airBlocks.add(airBlock.getBlock());
        }

        
    startMovement();       
    }

    private 
    void startMovement() {
        
    //..
     
        
    int minX min;
        
    int maxX max;

        @
    Override
        
    public void run() {
            
    minX++;
            
    maxX++;
         
            for (
    int wX minXwX <= maxXwX wX 1) {
                for (
    int wY minYwY <= maxYwY wY 1){
                    for (
    int wZ minZwZ <= maxZwZ wZ 1){
                        
    Location tmpBlock = new Location(player.getWorld(), wXwYwZ);
                        
    tmpBlock.getBlock().setType(material);
                        for (
    Block block airBlocks) {
                            
    block.getLocation().setX(wX);
                            
    block.getLocation().setY(wY);
                            
    block.getLocation().setZ(wZ);
                            
    block.setType(Material.AIR);
                        }
                    }
                }
            }
        }
    }


    This is just an example of what I did; this problem is so confusing :mad:
     
  4. Offline

    timtower Moderator Moderator

    @MrGriefer_ It creates a new location, every time you call getLocation().
    So you are setting a temporary variable.

    Instead:
    Have a list of locations, you can modify those.
     
  5. Offline

    MrGriefer_

    Hmm... Replaced Set<Block> with List<Location> but when setting the holes to the new location it'll set it to the entire wall. The wall just disappears.
    PHP:
    for (int wX minXwX <= maxXwX wX 1) {
        for (
    int wY minYwY <= maxYwY wY 1){
            for (
    int wZ minZwZ <= maxZwZ wZ 1){
                
    Location tmpBlock = new Location(player.getWorld(), wXwYwZ);
                
    tmpBlock.getBlock().setType(Material.ORANGE_TERRACOTTA);
                for (
    Location location airBlocks) {
                    
    location.setX(wX);
                    
    location.setY(wY);
                    
    location.setZ(wZ);
                    
    location.getBlock().setType(Material.AIR);
                }
            }
        }
    }
     
  6. Offline

    timtower Moderator Moderator

    @MrGriefer_ You do realize that you are setting the location of every air block to every block in the wall right?
    My suggestion:
    Make a list of pairs, Location, Material.
    Then for every iteration: get the locations, set all blocks to air (removing the old wall)
    Increment the location with the traveling direction.
    Set the block to the material attached to it.
     
  7. Offline

    MrGriefer_

    I know this sounds stupid but can you show me an example?
     
  8. Offline

    timtower Moderator Moderator

    Pseudo code
    Code:
    list<pair<Location, Material>> blocks; // Made when you created the wall
    for(pair : blocks){
    pair.location.getBlock().setType(air);
    pair.location.add(movementDirection);
    pair.location.getBlock().setType(pair.material);
    }
     
  9. Offline

    MrGriefer_

    I used the code below to remove the old wall and then set and move the new one, but I can't figure out how to do it with the Pair class, I used your code and nothing moves nor air blocks gets set.
    Code (open)

    Code:
    for (int wX = minX; wX <= maxX; wX = wX + 1) {
        for (int wY = minY; wY <= maxY; wY = wY + 1) {
            for (int wZ = minZ; wZ <= maxZ; wZ = wZ + 1) {
                Location tmpBlock = new Location(player.getWorld(), wX, wY, wZ);
                tmpBlock.getBlock().setType(Material.AIR);
            }
        }
    }
                   
    minX++;
    maxX++;
                   
    Material material = Material.ORANGE_TERRACOTTA;
    for (int wX = minX; wX <= maxX; wX = wX + 1) {
        for (int wY = minY; wY <= maxY; wY = wY + 1){
            for (int wZ = minZ; wZ <= maxZ; wZ = wZ + 1){
                Location tmpBlock = new Location(player.getWorld(), wX, wY, wZ);
                tmpBlock.getBlock().setType(material);
            }
        }
    }
     
  10. Offline

    timtower Moderator Moderator

    @MrGriefer_ 1. You only need a single loop.
    2. Make a list of pairs. First item is the location where the wall starts, second item is what type it is when the wall starts.

    You can almost copy my code btw. Only need to fill the list.
     
  11. Offline

    MrGriefer_

    The wall just disappears. I've tried debugging the code and everything seems to work fine.
    Code (open)

    PHP:
    private List<Pair<LocationMaterial>> blocks = new ArrayList<>();

    private 
    void addBlocks() {
        
    //..
        
    BlockVector3 min sel.getMinimumPoint();
        
    BlockVector3 max sel.getMaximumPoint();
       
        
    blocks.clear();   

        for (
    int x min.getBlockX(); <= max.getBlockX(); 1) {
            for (
    int y min.getBlockY(); <= max.getBlockY(); 1) {
                for (
    int z min.getBlockZ(); <= max.getBlockZ(); 1) {
                    
    Location tmpBlock = new Location(player.getWorld(), xyz);
                    
    tmpBlock.getBlock().setType(material);
                    
    blocks.add(new Pair<LocationMaterial>(tmpBlockmaterial));
                }
            }
        }

        for (
    int i 04i++) {
            
    int x = (int) (maxX Math.round(Math.random() * (minX maxX)));
            
    int y = (int) (maxY Math.round(Math.random() * (minY maxY)));
               
    int z = (int) (maxZ Math.round(Math.random() * (minZ maxZ)));
            
    Location airBlock = new Location(player.getWorld(), xyz);
            
    airBlock.getBlock().setType(Material.AIR);
            
    blocks.add(new Pair<LocationMaterial>(airBlockMaterial.AIR));
        }
    }

    private 
    void start() {
        
    //..

            
    int minX min;
            
    int maxX max;

            @
    Override
            
    public void run() {
                
    minX++;
                
    maxX++;

                for (
    int wX minXwX <= maxXwX wX 1) {
                    for (
    int wY minYwY <= maxYwY wY 1){
                        for (
    int wZ minZwZ <= maxZwZ wZ 1){
                            for (
    Pair<LocationMaterialblock blocks) {
                                
    block.getKey().getBlock().setType(Material.AIR);
                                
    block.getKey().setX(wX);
                                
    block.getKey().setY(wY);
                                
    block.getKey().setZ(wZ);
                                
    block.getKey().getBlock().setType(block.getValue());
                            }
                        }
                    }
                }
            }
    }
     
  12. Offline

    timtower Moderator Moderator

    @MrGriefer_ Do make sure that you don't have double locations in that list, you do have that now.
    And don't use a triple loop, you don't need it, please reference my code.
    You only need the loop ovee the pairs.
     
  13. Offline

    MrGriefer_

    Double locations? You mean I should use int instead of double?
    The triple loop is used to move the wall to the next new location, in your code you did pair.getKey().add(movementDirection); I’m guessing movementDirection is the new location, and if I add the new location to the pair the wall will stay as it is.
     
  14. Offline

    timtower Moderator Moderator

    No, you are adding new items to the list, items in the wall, those locations that you are adding are already in the list but with different type.

    You don't need the triple loop, if you look at the locations then they are all the same at the end.
    movementDirection is a Vector where one of the 3 values is 1 or -1.
     
  15. Offline

    MrGriefer_

    Okay thank you I finally got it working, just one question I keep getting NoClassDefFoundError javafx.util.Pair any idea how to fix this error. I followed these steps to install JavaFX.
     
  16. Offline

    timtower Moderator Moderator

    @MrGriefer_ Use a different pair class, if there is one.
    If not: make one, wrapper class that holds two types.
     
  17. Offline

    MrGriefer_

    Okay thank you I got it working, any idea on how to set the holes on the wall to another wall but the same location, for example if the holes in the wall are 2 blocks at the top left corner it will set the same thing for another wall top left corner. Take a look at the picture below:

    Image (open)
    [​IMG]
     
  18. Offline

    timtower Moderator Moderator

    @MrGriefer_ Order of the blocks is always the same, you can pick a certain index in the list to change.
     
  19. Offline

    MrGriefer_

    Sorry to bump this thread I didn't have the time to try this, can you give an example?
     
  20. Offline

    timtower Moderator Moderator

    Have 2 lists.
    Have a random function.
    Generate a couple random numbers.
    Those numbers are air blocks in both lists.
     
  21. Offline

    MrGriefer_

    Why do I need to have 2 lists, could you show me an example code?
     
  22. Offline

    timtower Moderator Moderator

    One for each wall.
    Don't have that now
     
  23. Offline

    MrGriefer_

    Okay, I finally got the time to try this. I created a new class called Wall which contains couple of information about the wall, like the list of pairs (List<Pair<Location, Material>>) and a Cuboid class, the issue is that I create a list in my main class which stores all the walls (List<Wall>) and an another list of Integers which I stored 3 random numbers, and then I did this:
    Code (open)

    PHP:
    private List<Wallwalls = new ArrayList<>();
    private List<
    Integernums = new ArrayList<>();

    public 
    void setAirBlocks() {
        
    nums.clear();
       
        
    Wall wall walls.get(0);
        for (
    int i 03i++) {
            
    Random random = new Random();
            
    int randomItem random.nextInt(wall.getBlocks().size());
            
    nums.add(randomItem);
        }

        for (
    Wall w walls) {
            for (
    int num nums) {
                
    Pair<LocationMaterialpair w.getBlocks().get(num);
                
    pair.getKey().getBlock().setType(Material.AIR);
            }
        }
    }


    If I created 4 walls and I run this function. Only two walls will have the air blocks and the other two will an another air blocks.
     
  24. Offline

    MrGriefer_

    Here is the problem in game, take a look at the picture below:
    Picture (open)
    [​IMG]


    As you can see, two walls have the same holes while the other two have the same holes but different than the previous ones. Any idea why is this happening?
     
  25. Offline

    timtower Moderator Moderator

    @MrGriefer_ Probably has something to do with the rotation.
    Keep all walls in the same direction, while shifting the starting position on a single axis.
     

Share This Page