Need help with falling blocks

Discussion in 'Spigot Plugin Development' started by Tnorfotkcab, May 31, 2018.

  1. Hello there,

    I'm creating a plugin (I'm not a regular in creating plugins, just doing it for my own entertainment and to release it to the public) and I have become stuck. I'm trying to get a falling object to pass through any material that is NOT air i.e. an open space. Until, of course, it hits the player's Y coordinate.

    I currently have a system set in place where the falling object will check the block beneath it and if it is not air then it will teleport to the next safest location with is made of air. However, the falling block lands and will no longer teleport but is still classed as a falling block type.

    [​IMG]

    Here is the code for what monstrosity I have so far:

    Code (Java):
    public void spawnAnvil(final Player p) {
            int initialHeight = 50;
            Location l = new Location(p.getWorld(), p.getLocation().getX(), p.getLocation().getY() + initialHeight, p.getLocation().getZ());
            anvil = p.getWorld().spawnFallingBlock(l, new MaterialData(Material.ANVIL));
            ((FallingBlock) anvil).setHurtEntities(true);
            ((FallingBlock) anvil).setDropItem(false);
            new BukkitRunnable() {
                int i = 0;
                public void run() {
                    int anvilY = (int) anvil.getLocation().getY();
                    int playerY = (int) p.getLocation().getY();
                    // while the block below the anvil is not air, teleport the anvil to where there is air
                    // until it is either 1 or 0 in relation to the players y coordinate

                    // get all the blocks in the range of the player y to the anvil y
                    ArrayList<Integer> safeY = new ArrayList<Integer>();
                    for (int i = anvilY; i > playerY; i--) { // count the safe locations from top down
                        Block b = p.getWorld().getBlockAt(new Location(p.getWorld(), p.getLocation().getX(), i, p.getLocation().getZ()));
                        if (b.getType() == Material.AIR) {
                            safeY.add(i); // add the safe locations in order from highest to lowest
                        }
                    }
                    if (p.getWorld().getBlockAt(new Location(p.getWorld(), (int)anvil.getLocation().getX(),(int)anvil.getLocation().getY()-1,(int)anvil.getLocation().getZ())).getType()!=Material.AIR){
                        Location loc = new Location(p.getWorld(), (int) anvil.getLocation().getX(),
                                                    (int) safeY.get(i)-1,
                                                    (int) anvil.getLocation().getZ());
                       
                        p.sendMessage("Attempting to teleport to: " + safeY.get(i));
                        anvil.teleport(loc);
                        p.sendMessage(anvil.getType()+"");
                        if (anvil instanceof Block)
                        System.out.println(i);
                        if (i==safeY.size()-1) i=0;
                        else
                        i++;
                    }

                    if ((int) anvil.getLocation().getX() != (int) p.getLocation().getX()) {
                        anvil.teleport(new Location(p.getWorld(), (int) p.getLocation().getX(), (int) anvil.getLocation().getY(), (int) p.getLocation().getZ()));
                    }
                    if ((int) anvil.getLocation().getZ() != (int) p.getLocation().getZ()) {
                        anvil.teleport(new Location(p.getWorld(), (int) p.getLocation().getX(), (int) anvil.getLocation().getY(), (int) p.getLocation().getZ()));
                    }

                    if ((int) anvil.getLocation().getY() == (int) p.getLocation().getY()) {
                        anvil.getWorld().getBlockAt(anvil.getLocation()).setType(Material.AIR);
                        p.sendMessage("Final resting place: " + anvil.getLocation());
                        cancel();
                    }

                }

            }.runTaskTimer(this, 0, 10);

        }
    Please do feel free to post suggestions on what to try, and ask questions for further explanations.
     
  2. ScarabCoder

    ScarabCoder Retired Resource Staff
    Retired

    If you're okay with learning new things, your best bet (at least the cleanest option) would be to use NMS. I've found trying to avoid vanilla mechanics like this never seem to go well. If you use NMS, you can control every single aspect about the entity except what it looks like (that means it's motion, whether or not it falls at all, etc). It is much harder to learn, but has way more potential.
     
    • Like Like x 1
  3. I will read up on NMS. Thank you :).
     
  4. NathanWolf

    Supporter

    I would suggest tagging the entity (use the metadata system) and then listening for EntityChangeBlockEvent. This is fired when your falling block changes into a normal block. At that point you can cancel the event and TP the block down- I think this should work out OK.
     
    • Agree Agree x 1