gt: 				&& spawner.getGameMode() == GameMode.CREATIVE) return;
context: package org.mctourney.autoreferee.listeners;
  
  import java.util.Iterator;
  import java.util.Map;
  import java.util.Set;
  
  import org.bukkit.ChatColor;
  import org.bukkit.GameMode;
  import org.bukkit.Location;
  import org.bukkit.Material;
  import org.bukkit.block.Block;
  import org.bukkit.entity.Entity;
  import org.bukkit.entity.EntityType;
  import org.bukkit.entity.Minecart;
  import org.bukkit.entity.Player;
  import org.bukkit.event.Cancellable;
  import org.bukkit.event.EventHandler;
  import org.bukkit.event.EventPriority;
  import org.bukkit.event.Listener;
  import org.bukkit.event.block.BlockBreakEvent;
  import org.bukkit.event.block.BlockPlaceEvent;
  import org.bukkit.event.entity.CreatureSpawnEvent;
  import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason;
  import org.bukkit.event.entity.EntityChangeBlockEvent;
  import org.bukkit.event.entity.EntityDamageEvent;
  import org.bukkit.event.entity.EntityExplodeEvent;
  import org.bukkit.event.entity.EntityTargetEvent;
  import org.bukkit.event.entity.ProjectileLaunchEvent;
  import org.bukkit.event.player.PlayerBedEnterEvent;
  import org.bukkit.event.player.PlayerBucketEmptyEvent;
  import org.bukkit.event.player.PlayerBucketFillEvent;
  import org.bukkit.event.player.PlayerInteractEntityEvent;
  import org.bukkit.event.player.PlayerInteractEvent;
  import org.bukkit.event.player.PlayerMoveEvent;
  import org.bukkit.event.player.PlayerPickupItemEvent;
  import org.bukkit.event.player.PlayerTeleportEvent;
  import org.bukkit.event.vehicle.VehicleEnterEvent;
  import org.bukkit.event.weather.WeatherChangeEvent;
  import org.bukkit.plugin.Plugin;
  
  import org.mctourney.autoreferee.AutoRefMatch;
  import org.mctourney.autoreferee.AutoRefPlayer;
  import org.mctourney.autoreferee.AutoRefTeam;
  import org.mctourney.autoreferee.AutoReferee;
  import org.mctourney.autoreferee.AutoRefMatch.MatchStatus;
  import org.mctourney.autoreferee.AutoRefMatch.Role;
  import org.mctourney.autoreferee.goals.BlockGoal;
  import org.mctourney.autoreferee.regions.AutoRefRegion;
  import org.mctourney.autoreferee.regions.AutoRefRegion.Flag;
  import org.mctourney.autoreferee.util.BlockData;
  import org.mctourney.autoreferee.util.LocationUtil;
  
  import com.google.common.collect.Maps;
  import com.google.common.collect.Sets;
  
  public class ZoneListener implements Listener
  {
  	AutoReferee plugin = null;
  
  	// distance a player may travel outside of their lane without penalty
  	private static final double SAFE_TRAVEL_DISTANCE = 1.595;
  
  	// minimum teleport distance worth reporting to streamers
  	private static final double LONG_TELE_DISTANCE = 6.0;
  
  	public static final double SNEAK_DISTANCE = 0.301;
  	public static final double FREEFALL_THRESHOLD = 0.350;
  
  	public static final Set<Material> RESTRICTED_BLOCKS = Sets.newHashSet
  	(	Material.COMMAND
  	);
  
  	public ZoneListener(Plugin p)
  	{ plugin = (AutoReferee) p; }
  
  	@EventHandler(priority=EventPriority.MONITOR)
  	public void playerMove(PlayerMoveEvent event)
  	{
  		Player player = event.getPlayer();
  		AutoRefMatch match = plugin.getMatch(player.getWorld());
  		if (match == null) return;
  
  		Location locUnder = event.getTo().clone().add(0.0, -0.1, 0.0);
  		int blockUnder = match.getWorld().getBlockTypeIdAt(locUnder);
  		boolean onGround = (blockUnder != Material.AIR.getId());
  
  		AutoRefPlayer apl = match.getPlayer(player);
  		if (apl == null)
  		{
  			// if the player is not on a team and has left the start area, teleport back
  			if (!match.isSpectator(player) && !match.inStartRegion(event.getTo()) && onGround)
  			{
  				player.teleport(match.getWorldSpawn());
  				player.setFallDistance(0.0f);
  			}
  			return;
  		}
  
  		AutoRefTeam team = apl.getTeam();
  		if (team == null) return;
  
  		// announce region (for cosmetic regions)
  		for (AutoRefRegion reg : team.getRegions())
  			if (reg.getName() != null && reg.isEnterEvent(event)) reg.announceRegion(apl);
  
  		double fallspeed = event.getFrom().getY() - event.getTo().getY();
  		Location exit = apl.getExitLocation();
  
  		// don't bother if the player isn't in survival mode
  		if (player.getGameMode() != GameMode.SURVIVAL
  			|| match.inStartRegion(event.getTo())) return;
  
  		// if a player leaves the start region...
  		if (!match.inStartRegion(event.getTo()))
  		{
  			if (match.getCurrentState().inProgress())
  			{
  				// if they are leaving the start region, clear everything
  				if (match.inStartRegion(event.getFrom()) && !apl.isActive()) apl.reset();
  
  				// one way or another, the player is now active
  				apl.setActive();
  			}
  
  			else if (match.getCurrentState().isBeforeMatch())
  			{ if (onGround) apl.die(null, false); return; }
  		}
  
  		// if they have left their region, mark their exit location
  		if (!team.canEnter(event.getTo(), 0.3) && !player.isSleeping())
  		{
  			// player is sneaking off the edge and not in freefall
  			if (player.isSneaking() && team.canEnter(event.getTo()) && fallspeed < FREEFALL_THRESHOLD);
  
  			// if there is no exit position, set the exit position
  			else if (exit == null) apl.setExitLocation(player.getLocation());
  
  			// if there is an exit position and they aren't falling, kill them
  			else if (exit != null && fallspeed < FREEFALL_THRESHOLD && onGround)
  				apl.die(AutoRefPlayer.VOID_DEATH, true);
  		}
  
  		// player inside region
  		else
  		{
  			// if there is an exit location
  			if (exit != null)
  			{
  				// if the player traveled too far through the void, kill them
  				if (player.getLocation().distance(exit) > SAFE_TRAVEL_DISTANCE)
  					apl.die(AutoRefPlayer.VOID_DEATH, true);
  
  				// reset exit location since player in region
  				apl.setExitLocation(null);
  			}
  		}
  	}
  
  	@EventHandler(priority=EventPriority.MONITOR, ignoreCancelled=true)
  	public void enderpearlThrow(ProjectileLaunchEvent event)
  	{
  		// if the match is not under our control, ignore
  		AutoRefMatch match = plugin.getMatch(event.getEntity().getWorld());
  		if (match == null || match.getCurrentState() == MatchStatus.NONE) return;
  
  		if (event.getEntityType() == EntityType.ENDER_PEARL)
  		{
  			Player player = (Player) event.getEntity().getShooter();
  			AutoRefPlayer apl = match.getPlayer(player);
  
  			if (apl != null && apl.getTeam().hasFlag(player.getLocation(), Flag.NO_ENTRY))
  			{
  				String msg = ChatColor.DARK_GRAY + apl.getDisplayName() +
  					ChatColor.DARK_GRAY + " has thrown an enderpearl while out of bounds.";
  				for (Player ref : match.getReferees()) ref.sendMessage(msg);
  			}
  		}
  	}
  
  	public boolean validPlayer(Player player)
  	{
  		// if the match is not under our control, allowed
  		AutoRefMatch match = plugin.getMatch(player.getWorld());
  		if (match == null || match.getCurrentState() == MatchStatus.NONE) return true;
  
  		// if we are in practice mode, whatever...
  		if (match.isPracticeMode()) return true;
  
  		Role role = match.getRole(player);
  
  		// if the player is a referee or is flying, nothing is off-limits
  		if (role == Role.REFEREE || (match.getCurrentState().inProgress()
  			&& player.isFlying() && role == Role.PLAYER)) return true;
  
  		// if the match isn't currently in progress, a player should
  		// not be allowed to place or destroy blocks anywhere
  		if (!match.getCurrentState().inProgress()) return false;
  
  		// if the player is not in their lane, they shouldn't be allowed to interact
  		AutoRefPlayer apl = match.getPlayer(player);
  		if (apl == null || apl.getExitLocation() != null) return false;
  
  		// seems okay!
  		return true;
  	}
  
  	@EventHandler(priority=EventPriority.MONITOR)
  	public void playerPickup(PlayerPickupItemEvent event)
  	{
  		// if this isn't a match, skip it
  		AutoRefMatch match = plugin.getMatch(event.getPlayer().getWorld());
  		if (match == null) return;
  
  		if (match.elevatedItem.containsKey(event.getItem().getUniqueId())
  			&& match.isPlayer(event.getPlayer()))
  		{
  			String itemname = new BlockData(event.getItem().getItemStack()).getDisplayName();
  			String msg = match.getDisplayName(event.getPlayer()) + ChatColor.DARK_GRAY +
  				" picked up " + itemname + ChatColor.DARK_GRAY + " from an item elevator.";
  			match.setLastNotificationLocation(event.getItem().getLocation());
  
  			for (Player ref : match.getReferees()) ref.sendMessage(msg);
  			AutoReferee.log(msg);
  		}
  	}
  
  	@EventHandler(priority=EventPriority.HIGHEST, ignoreCancelled=true)
  	public void blockPlace(BlockPlaceEvent event)
  	{
  		blockEvent(event, event.getPlayer(), event.getBlock());
  	}
  
  	@EventHandler(priority=EventPriority.HIGHEST, ignoreCancelled=true)
  	public void blockFall(EntityChangeBlockEvent event)
  	{
  		// if this isn't a match, skip it
  		AutoRefMatch match = plugin.getMatch(event.getBlock().getWorld());
  		if (match == null) return;
  
  		Block block = event.getBlock();
  		if (event.getEntityType() == EntityType.FALLING_BLOCK)
  		{
  			for (AutoRefRegion reg : match.getRegions())
  				if (reg.is(AutoRefRegion.Flag.NO_BUILD) && reg.containsBlock(block))
  				{ event.setCancelled(true); return; }
  		}
  	}
  
  	@EventHandler(priority=EventPriority.HIGHEST, ignoreCancelled=true)
  	public void blockBreak(BlockBreakEvent event)
  	{
  		Player player = event.getPlayer();
  		Block b = event.getBlock();
  
  		AutoRefMatch match = plugin.getMatch(b.getWorld());
  		if (match == null) return;
  
  		if (!validPlayer(player))
  		{ event.setCancelled(true); return; }
  
  		AutoRefPlayer apl = match.getPlayer(player);
  		if (apl != null && apl.getTeam().hasFlag(b, AutoRefRegion.Flag.NO_BUILD, false))
  		{ event.setCancelled(true); return; }
  	}
  
  	@EventHandler(priority=EventPriority.HIGHEST, ignoreCancelled=true)
  	public void bucketFill(PlayerBucketFillEvent event)
  	{
  		blockEvent(event, event.getPlayer(),
  			event.getBlockClicked().getRelative(event.getBlockFace()));
  	}
  
  	@EventHandler(priority=EventPriority.HIGHEST, ignoreCancelled=true)
  	public void bucketEmpty(PlayerBucketEmptyEvent event)
  	{
  		blockEvent(event, event.getPlayer(),
  			event.getBlockClicked().getRelative(event.getBlockFace()));
  	}
  
  	public void blockEvent(Cancellable event, Player player, Block block)
  	{
  		AutoRefMatch match = plugin.getMatch(block.getWorld());
  		if (match == null) return;
  
  		if (!validPlayer(player))
  		{ event.setCancelled(true); return; }
  
  		AutoRefPlayer apl = match.getPlayer(player);
  		if (apl != null && apl.getTeam().hasFlag(block, AutoRefRegion.Flag.NO_BUILD))
  		{ event.setCancelled(true); return; }
  	}
  
  	@EventHandler(priority=EventPriority.HIGHEST, ignoreCancelled=true)
  	public void blockInteract(PlayerInteractEvent event)
  	{
  		Player player = event.getPlayer();
  		Block block = event.getClickedBlock();
  
  		AutoRefMatch match = plugin.getMatch(block.getWorld());
  		if (match == null) return;
  
  		if (match.isPlayer(player))
  		{
  			AutoRefPlayer apl = match.getPlayer(player);
  			boolean noaccess = apl.getTeam().hasFlag(block, Flag.NO_ACCESS);
  
  			if (!match.getPlayer(player).isInsideLane() || (noaccess && !event.isBlockInHand()))
  			{ event.setCancelled(true); return; }
  
  			if (match.isStartMechanism(block) && !match.getStartMechanism(block).canFlip(match))
  			{ event.setCancelled(true); return; }
  
  			if (!validPlayer(player))
  			{ event.setCancelled(true); return; }
  
  			if (RESTRICTED_BLOCKS.contains(block.getType()))
  			{ event.setCancelled(true); return; }
  		}
  	}
  
  	@EventHandler(priority=EventPriority.HIGHEST, ignoreCancelled=true)
  	public void entityInteract(PlayerInteractEntityEvent event)
  	{
  		Player player = event.getPlayer();
  		Location loc = event.getRightClicked().getLocation();
  
  		AutoRefMatch match = plugin.getMatch(loc.getWorld());
  		if (match == null) return;
  
  		if (!validPlayer(player))
  		{ event.setCancelled(true); return; }
  
  		AutoRefPlayer apl = match.getPlayer(player);
  		if (apl != null)
  		{
  			if (!apl.isInsideLane() || apl.getTeam().hasFlag(loc, Flag.NO_ACCESS))
  			{ event.setCancelled(true); return; }
  		}
  	}
  
  	@EventHandler(priority=EventPriority.HIGHEST)
  	public void creatureSpawn(CreatureSpawnEvent event)
  	{
  		AutoRefMatch match = plugin.getMatch(event.getEntity().getWorld());
  		if (match == null || match.getCurrentState() == MatchStatus.NONE) return;
  
  		if (event.getSpawnReason() == SpawnReason.SPAWNER_EGG)
  		{
  			Player spawner = null;
  			double distance = Double.POSITIVE_INFINITY;
  
  			// get the player who spawned this entity
  			Location loc = event.getEntity().getLocation();
  			for (Player pl : event.getEntity().getWorld().getPlayers())
  			{
  				double d = loc.distanceSquared(pl.getLocation());
  				if (d < distance && pl.getItemInHand() != null &&
  					pl.getItemInHand().getType() == Material.MONSTER_EGG)
  				{ spawner = pl; distance = d; }
  			}
  
  			// if the player who spawned this creature can configure...
  			if (spawner != null && spawner.hasPermission("autoreferee.configure")
  