Solved Placing (and changing) pressure plates.

Discussion in 'Plugin Development' started by Neuromante, Mar 26, 2014.

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

    Neuromante

    Hello!

    I'm trying to write a small plugin (Bukkit 1.6.4-R2.0) that places randomly pressure plates that change its type when pressed (This is, a wood plate changing to a stone one, for instance). The idea is that if a player steps three times on the same pressure plate, the plate will change three times of type.

    So, right now I have (almost) everything set up:
    1) A function that actually "paints" the block where I want:
    Code:java
    1. _world.getBlockAt(x, y + 3, z).setType(Material.WOOD_PLATE);

    2) The eventHandler which will capture the event when Steve steps:
    Code:java
    1. @EventHandler
    2. public final void onPlayerInteract(PlayerInteractEvent e) {
    3. if (e.getAction() == Action.PHYSICAL) {
    4. e.getClickedBlock().setType(Material.STONE_PLATE);
    5. }
    6. }


    But...
    ...it seems that when the event fires, the call to setType changes the type, but the "new" pressure plate stays pressed, so if the player steps again onto it, the event does not fires and I can't capture it again.
    I've failed to find any kind of "isActive/isPressed" value in the API,I've seen the org.bukkit.material.PressurePlate class in the API but can't find where I can use it (also, it doesn't have the functions I need), and right now I'm basically clueless. My only idea is creating some kind of timer in a synchronized function to change the type of the pressed blocks one or two seconds after they are touched (And it wouldn't solve the issue, as a player could just stand over it and screw me again).

    Any idea? Something I'm missing?
     
  2. Offline

    2MBKindiegames

    I'm guessing the blockstate is never renewed, maybe something like
    will fix your problem...
     
  3. Offline

    Neuromante

    Sir, you are a hero. It worked, thanks!

    Edit: I talked too fast. Trying to figure out what's happening now to update...
     
  4. Offline

    2MBKindiegames

    You are very welcome!
    If you need me again, just PM me!

    PS: If you don't need this topic anymore, please mark it as SOLVED!
     
  5. Offline

    Neuromante

    Well, that's kind of weird.

    I have the pressure_plates with the line provided:
    Code:java
    1. e.getClickedBlock().setType(Material.STONE_PLATE)
    2. e.getClickedBlock().getState().update();

    But it seems that the "update" action occurs at random times. I have two plates placed near. I step on one, then on the other, and both of them changes, but only one of them "resets" itself to "unpressed" position. 30 seconds later, the other plate resets itself.
    Then, I have three plates. I press all of them and they reset like a charm. Then n plates that don't reset...

    I'm tinkering a bit with the getState() function:
    Code:java
    1.  
    2. e.getClickedBlock().setType(Material.STONE_PLATE);
    3. e.getClickedBlock().getState().update();
    4. PressurePlate pp = (PressurePlate)e.getClickedBlock().getState().getData();
    5. if(pp.isPressed())
    6. _log.info("%s",Logger.PLAYER,"Pressed!");
    7. else
    8. _log.info("%s",Logger.PLAYER,"No pressed!");
    9.  

    And EACH time I push a block, I get the "No pressed" message. (I've tried also to do the check before the update call with the same result).
     
  6. Offline

    2MBKindiegames

    I'm very sorry, I can't find the problem, maybe someone else can...
     
  7. Offline

    Neuromante

    I've been doing some research to no avail.

    It seems that using the (deprecated) Block.setData() with the 0 value (link to the minecraft wiki) I can set the pressure plate to reset itself, but...
    a) is a deprecated method, there isn't really any non-deprecated way to do this?
    b) it doesn't really work at all. As if I did nothing.

    I'm considering a separate routine which resets every second all the plates in the map, but I see this as an awful solution (and also, what happens if there is anyone atop of any of the plates).

    So... any ideas? Anyone? :(
     
  8. Offline

    curlyfries1999

    Try adding 1 tick of delay
     
  9. Offline

    Neuromante

    The delay worked! Kind of :p

    I blatantly copied the code written here and added a private class (I'm not big fan of declaring classes in the function calls) to handle the status checking as a scheduled task: Now I have a task in the scheduler that waits one second and then changes the type of the block.

    The ugly part comes that, as a player could just be standing over the pressure plate for two seconds, and the problem would persist, so... I make the task add itself to the scheduler if the block is still pressed.

    Code below:

    Code:java
    1. private class CustomRunnable implements Runnable{
    2. private PlayerInteractEvent _e;
    3. private Plugin _p;
    4. private CustomRunnable(PlayerInteractEvent e, Plugin p)
    5. {_e=e;_p=p;}
    6. public void run()
    7. {
    8. PressurePlate pp = (PressurePlate)_e.getClickedBlock().getState().getData();
    9. if(!pp.isPressed())
    10. {
    11. _e.getClickedBlock().setType(Material.STONE_PLATE);
    12. _e.getClickedBlock().getState().update(true);
    13. }
    14. else
    15. _p.getServer().getScheduler().scheduleSyncDelayedTask(_plugin,new CustomRunnable(_e,_p),1*20L);
    16. }
    17.  
    18. }


    And the new code for the event:
    Code:java
    1.  
    2. if(e.getClickedBlock().getType()==Material.WOOD_PLATE)
    3. {
    4. _plugin.getServer().getScheduler().scheduleSyncDelayedTask(_plugin,new CustomRunnable(e,_plugin),1*20L);
    5. }
    6.  


    I don't really like scheduling over and over the same task, but it seems that just waiting for isPressed to be false doesn't work at all.
     
Thread Status:
Not open for further replies.

Share This Page