user3397648
user3397648

Reputation: 37

Setting the block underneath any player to glowstone, then setting it back to the original material

I'm making a Bukkit plugin that will change the block underneath any player to glowstone.

The scheduler isn't working. The ground will change to glowstone but the glowstone block won't revert back to what it originally was.

@EventHandler
public void onStep(PlayerMoveEvent pme) {
    Player player = pme.getPlayer();
    Location locUnderPlayer = player.getLocation();
    locUnderPlayer.setY(locUnderPlayer.getY() - 1);
    Location locForScheduler = player.getLocation();
    locForScheduler.setY(locForScheduler.getY() + 1);
    final Material materialForScheduler = locForScheduler.getBlock().getType();
    Block block = locUnderPlayer.getBlock();
    Material m = player.getItemInHand().getType();
    if (m == Material.GLOWSTONE) {
        if (block.getType() != Material.AIR && block.getType() != Material.WATER && block.getType() != Material.STATIONARY_WATER && block.getType() != Material.LAVA && block.getType() != Material.STATIONARY_LAVA && block.getType() != Material.REDSTONE_WIRE && block.getType() != Material.REDSTONE_COMPARATOR && block.getType() != Material.REDSTONE_TORCH_ON && block.getType() != Material.REDSTONE_TORCH_OFF) {
            block.setType(Material.GLOWSTONE);
            Bukkit.getScheduler().scheduleSyncDelayedTask(Magic.getInstance(), new Runnable() {
                public void run() {
                    block.setType(materialForScheduler);
                }
            }, 1 * 10);
        }
    }
}

Upvotes: 2

Views: 8304

Answers (4)

J22929
J22929

Reputation: 5

EDIT: Late huh, my bad well I guess anyone else could use it There's another option:

1) get block under player

Block block = (player.getWorld, player.getLocation().getX(), 
    ,player.getWorld, player.getLocation().getY()-1,
    ,player.getWorld, player.getLocation().getZ());

2) get the block and save it as a block state

Blockstate bs = block.getState();

3) set the block to glowstone

block.setType(Material.GLOWSTONE);

4) this reverts it back to its last saved state

bs.update(true)

5) (if you want) create a delay

Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(this new Runnable() {
          public void run() {
   //put delayed code here
   bs.update(true);

}
            }, 20 * seconds);

Upvotes: 0

Jojodmo
Jojodmo

Reputation: 23616

To get the block underneath a player, you could use:

Block block = player.getLocation().subtract(0, 1, 0).getBlock();

Which gets the player's location, subtracts 1 from the Y-axis, and then gets the block (hence getting the block under the player).

Then to get the type, you could use block.getType():

Material type = block.getType();

To set the block to glowstone, you could use block.setType(Material):

block.setType(Material.GLOWSTONE);

So, if you wanted to set the block under a player to glowstone, then immediately turn it back to the original block, you could use:

Block block = player.getLocation().subtract(0, 1, 0).getBlock(); //get the block
Material type = block.getType(); //get the block's type
block.setType(Material.GLOWSTONE); //set the block's material to glowstone
block.setType(type); //set the block's material back to the original material

But to have a delay between setting the block to glowstone then setting it back to the original block (in your case, the delay is 10 ticks) you could use a Runnable task:

final Block block = player.getLocation().subtract(0, 1, 0).getBlock(); //get the block
final Material type = block.getType(); //get the block's type

block.setType(Material.GLOWSTONE); //set the block's material to glowstone

Bukkit.getScheduler().runTaskLater(Magic.getInstance(), new Runnable(){
  public void run(){
    block.setType(type); //set the block back to the original block
  }
},10L);

We would want to make sure that the block beneath the player is not already glowstone, to insure that the block change does not become permanent. This could be done using simply:

if(!type.equals(Material.GLOWSTONE))

If we did not check for this, then a player could move with glowstone in their hand, hence setting the block underneath them to glowstone, and then starting a timer to set it back to the original block. But, if the player moves while the timer is in session (for example, 5 ticks after they last moved), the block underneath them would permanently change to glowstone.

So, your code could look something like this:

@EventHandler
public void onStep(PlayerMoveEvent pme) {
  Player player = pme.getPlayer(); //get the player in the event
  final Block block = player.getLocation().subtract(0, 1, 0).getBlock(); //get the block
  final Material type = block.getState().getType(); //get the block's material
  if(!type.equals(Material.GLOWSTONE)){//don't change the block if it's already glowstone
    if(player.getItemInHand() != null){//make sure the item in the player's hand is not null, to avoid a null pointer
      Material m = player.getItemInHand().getType(); //get the item in the player's hand
      if(m == Material.GLOWSTONE){ //check if the item in the player's hand is glowstone
        if(type != Material.AIR && type != Material.WATER && type != Material.STATIONARY_WATER && type != Material.LAVA && type != Material.STATIONARY_LAVA && type != Material.REDSTONE_WIRE && type != Material.REDSTONE_COMPARATOR && type != Material.REDSTONE_TORCH_ON && type != Material.REDSTONE_TORCH_OFF){
          block.setType(Material.GLOWSTONE);//set the block type to glowstone
          Bukkit.getScheduler().runTaskLater(Magic.getInstance(), new Runnable() {
            public void run(){
              block.setType(type); //set the block type back to the original type
            }
          },10L);
        }
      }
    }
  }
}

Also, you could reduce this if statement:

if(type != Material.AIR && type != Material.WATER && type != Material.STATIONARY_WATER && type != Material.LAVA && type != Material.STATIONARY_LAVA && type != Material.REDSTONE_WIRE && type != Material.REDSTONE_COMPARATOR && type != Material.REDSTONE_TORCH_ON && type != Material.REDSTONE_TORCH_OFF)

into simply type.isSolid():

if(type.isSolid())

Upvotes: 8

k3v
k3v

Reputation: 119

The issue is because you are not checking if the block is already glowstone. So if you are running a temporary glowstone through the code, it will become permanent.

Upvotes: 0

user3453226
user3453226

Reputation:

@EventHandler(priority = EventPriority.MONITOR)
public void onMonitor(PlayerMoveEvent event) {
    if (!event.isCancelled()) {
        Player player = event.getPlayer();
        if (player.getItemInHand().getType() == Material.GLOWSTONE) {
            Block block = event.getTo().subtract(0D, 1D, 0D).getBlock();
            Material type = block.getType();
            if (type.isSolid()) {
                if (!Restore.locked.contains(block)) {
                    Restore restore = new Restore(block, type, block.getData());
                    block.setType(Material.GLOWSTONE);
                    restore.runTaskLater(Plugin, 10L);
                }
            }
        }
    }
}

public class Restore extends BukkitRunnable {
    public static Set<Block> locked = new HashSet<Block>();
    private Block block;
    private Material type;
    private byte data;
    public Restore(Block block, Material type, byte data) {
        this.block = block;
        this.type = type;
        this.data = data;
        locked.add(block);
    }
    @Override
    public void run() {
        block.setType(type);
        block.setData(data);
        locked.remove(block);
    }
}

Upvotes: 0

Related Questions