Browse Source

Workaround a CB bug by tracking piston events

There is a bug in Craftbukkit that causes piston events to fire
multiple times. We need to keep track of the extend and retract events
to see which piston events should be processed.
TfT_02 11 years ago
parent
commit
906609696b

+ 8 - 0
src/main/java/com/gmail/nossr50/listeners/BlockListener.java

@@ -63,6 +63,10 @@ public class BlockListener implements Listener {
      */
      */
     @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
     @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
     public void onBlockPistonExtend(BlockPistonExtendEvent event) {
     public void onBlockPistonExtend(BlockPistonExtendEvent event) {
+        if (!EventUtils.shouldProcessEvent(event.getBlock(), true)) {
+            return;
+        }
+
         List<Block> blocks = event.getBlocks();
         List<Block> blocks = event.getBlocks();
         BlockFace direction = event.getDirection();
         BlockFace direction = event.getDirection();
         Block futureEmptyBlock = event.getBlock().getRelative(direction); // Block that would be air after piston is finished
         Block futureEmptyBlock = event.getBlock().getRelative(direction); // Block that would be air after piston is finished
@@ -93,6 +97,10 @@ public class BlockListener implements Listener {
      */
      */
     @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
     @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
     public void onBlockPistonRetract(BlockPistonRetractEvent event) {
     public void onBlockPistonRetract(BlockPistonRetractEvent event) {
+        if (!EventUtils.shouldProcessEvent(event.getBlock(), false)) {
+            return;
+        }
+
         if (!event.isSticky()) {
         if (!event.isSticky()) {
             return;
             return;
         }
         }

+ 1 - 0
src/main/java/com/gmail/nossr50/mcMMO.java

@@ -112,6 +112,7 @@ public class mcMMO extends JavaPlugin {
     public final static String disarmedItemKey     = "mcMMO: Disarmed Item";
     public final static String disarmedItemKey     = "mcMMO: Disarmed Item";
     public final static String playerDataKey       = "mcMMO: Player Data";
     public final static String playerDataKey       = "mcMMO: Player Data";
     public final static String greenThumbDataKey   = "mcMMO: Green Thumb";
     public final static String greenThumbDataKey   = "mcMMO: Green Thumb";
+    public final static String pistonDataKey       = "mcMMO: Piston State";
 
 
     public static FixedMetadataValue metadataValue;
     public static FixedMetadataValue metadataValue;
 
 

+ 23 - 0
src/main/java/com/gmail/nossr50/util/EventUtils.java

@@ -8,6 +8,7 @@ import org.bukkit.entity.Fish;
 import org.bukkit.entity.Player;
 import org.bukkit.entity.Player;
 import org.bukkit.event.player.PlayerFishEvent;
 import org.bukkit.event.player.PlayerFishEvent;
 import org.bukkit.inventory.ItemStack;
 import org.bukkit.inventory.ItemStack;
+import org.bukkit.metadata.FixedMetadataValue;
 import org.bukkit.plugin.PluginManager;
 import org.bukkit.plugin.PluginManager;
 
 
 import com.gmail.nossr50.mcMMO;
 import com.gmail.nossr50.mcMMO;
@@ -194,4 +195,26 @@ public class EventUtils {
 
 
         return event;
         return event;
     }
     }
+
+    /**
+     * There is a bug in CraftBukkit that causes piston events to
+     * fire multiple times. Check this method to see if the piston event
+     * should be processed.
+     *
+     * @param block      Block object of the piston block
+     * @param isExtendEvent should be true when called from BlockPistonExtendEvent
+     *
+     * @return true if the PistonEvent should be processed, false otherwise
+     */
+    public static boolean shouldProcessEvent(Block block, boolean isExtendEvent) {
+        String pistonAction = isExtendEvent ? "EXTEND" : "RETRACT";
+        String lastAction = block.hasMetadata(mcMMO.pistonDataKey) ? block.getMetadata(mcMMO.pistonDataKey).get(0).asString() : "";
+
+        if (!lastAction.equals(pistonAction)) {
+            block.setMetadata(mcMMO.pistonDataKey, new FixedMetadataValue(mcMMO.p, pistonAction));
+            return true;
+        }
+
+        return false;
+    }
 }
 }