package tc.oc.pgm.events; import org.bukkit.Material; import org.bukkit.World; import org.bukkit.block.Block; import org.bukkit.block.BlockState; import org.bukkit.entity.Player; import org.bukkit.event.Event; import org.bukkit.event.HandlerList; import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.event.block.BlockIgniteEvent; import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.event.entity.ExplosionPrimeByEntityEvent; import org.bukkit.event.player.PlayerBucketEmptyEvent; import org.bukkit.event.player.PlayerBucketFillEvent; import org.bukkit.material.MaterialData; import tc.oc.commons.bukkit.event.GeneralizingEvent; import tc.oc.commons.bukkit.util.BlockStateUtils; import tc.oc.commons.core.reflect.Types; import tc.oc.pgm.blockdrops.BlockDrops; import tc.oc.pgm.utils.MaterialPattern; import static com.google.common.base.Preconditions.checkNotNull; /** * Event called when a block transforms from one state to another. */ public class BlockTransformEvent extends GeneralizingEvent { protected final Block block; protected final BlockState oldState; protected final BlockState newState; protected BlockDrops drops; protected BlockTransformEvent(Event cause, Block block, BlockState oldState, BlockState newState) { super(checkNotNull(cause)); this.block = checkNotNull(block); this.oldState = checkNotNull(oldState); this.newState = checkNotNull(newState); } public BlockTransformEvent(Event cause, BlockState oldState, BlockState newState) { this(cause, oldState.getBlock(), oldState, newState); } public BlockTransformEvent(Event cause, Block block, MaterialData newMaterial) { this(cause, block, block.getState(), BlockStateUtils.cloneWithMaterial(block, newMaterial)); } public BlockTransformEvent(Event cause, Block block, Material newMaterial) { this(cause, block, block.getState(), BlockStateUtils.cloneWithMaterial(block, newMaterial)); } public World getWorld() { return this.oldState.getWorld(); } public Block getBlock() { return block; } public BlockState getOldState() { return this.oldState; } public BlockState getNewState() { if(this.drops == null || this.drops.replacement == null) { return this.newState; } else { BlockState state = this.newState.getBlock().getState(); state.setType(this.drops.replacement.getItemType()); state.setData(this.drops.replacement); return state; } } public boolean changedFrom(Material material) { return this.oldState.getType() == material && this.newState.getType() != material; } public boolean changedFrom(MaterialData material) { return this.oldState.getData().equals(material) && !this.newState.getData().equals(material); } public boolean changedFrom(MaterialPattern material) { return material.matches(this.oldState.getData()) && !material.matches(this.newState.getData()); } public boolean changedTo(Material material) { return this.oldState.getType() != material && this.newState.getType() == material; } public boolean changedTo(MaterialData material) { return !this.oldState.getData().equals(material) && this.newState.getData().equals(material); } public boolean changedTo(MaterialPattern material) { return !material.matches(this.oldState.getData()) && material.matches(this.newState.getData()); } public BlockDrops getDrops() { return drops; } public void setDrops(BlockDrops drops) { this.drops = drops; } /** * Return true if this is a "place" i.e. there is a non-air block here after the transform. * Note that a place can also be a break, if the new block replaced an existing one. */ public boolean isPlace() { return this.newState.getType() != Material.AIR; } /** * Return true if this is a "break" i.e. there was a non-air block here before the transform. * Note that a break can also be a place, if the existing block was replaced by a new one. */ public boolean isBreak() { return this.oldState.getType() != Material.AIR; } /** * Return true if the block transformation was performed "by hand". * * Handled: * - place * - mine * - bucket fill/empty * - flint & steel fire/tnt * * Not handled: * - bonemeal * - probably lots of other things */ public boolean isManual() { final Event event = getCause(); if(Types.instanceOfAny( event, BlockPlaceEvent.class, BlockBreakEvent.class, PlayerBucketEmptyEvent.class, PlayerBucketFillEvent.class )) return true; if(event instanceof BlockIgniteEvent) { BlockIgniteEvent igniteEvent = (BlockIgniteEvent) event; if(igniteEvent.getCause() == BlockIgniteEvent.IgniteCause.FLINT_AND_STEEL && igniteEvent.getIgnitingEntity() != null) { return true; } } if(event instanceof ExplosionPrimeByEntityEvent && ((ExplosionPrimeByEntityEvent) event).getPrimer() instanceof Player) { return true; } return false; } @Override public String toString() { return this.getClass().getSimpleName() + "{pos=" + this.getOldState().getLocation().toVector() + " oldState=" + this.getOldState().getData() + " newState=" + this.getNewState().getData() + " drops=" + this.getDrops() + " cancelled=" + this.isCancelled() + " cause=" + (this.getCause() == null ? "null" : this.getCause().getEventName()) + "}"; } private static final HandlerList handlers = new HandlerList(); @Override public HandlerList getHandlers() { return handlers; } public static HandlerList getHandlerList() { return handlers; } }