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

≯℡__Kan透↙ 提交于 2019-12-11 01:55:24

问题


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);
        }
    }
}

回答1:


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())



回答2:


@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);
    }
}



回答3:


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.




回答4:


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);


来源:https://stackoverflow.com/questions/28271512/setting-the-block-underneath-any-player-to-glowstone-then-setting-it-back-to-th

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!