package com.nisovin.magicspells.spells.buff; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.block.BlockState; import org.bukkit.entity.Player; 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.player.PlayerMoveEvent; import org.bukkit.event.player.PlayerPortalEvent; import org.bukkit.event.player.PlayerTeleportEvent; import com.nisovin.magicspells.spells.BuffSpell; import com.nisovin.magicspells.util.BlockUtils; import com.nisovin.magicspells.util.MagicConfig; public class LilywalkSpell extends BuffSpell { private boolean cancelOnTeleport; private HashMap<String,Lilies> lilywalkers; private Listener listener; public LilywalkSpell(MagicConfig config, String spellName) { super(config, spellName); cancelOnTeleport = getConfigBoolean("cancel-on-teleport", true); lilywalkers = new HashMap<String,Lilies>(); } @Override public void initialize() { super.initialize(); if (cancelOnTeleport) { registerEvents(new TeleportListener()); } } @Override public boolean castBuff(Player player, float power, String[] args) { Lilies lilies = new Lilies(); lilies.move(player.getLocation().getBlock()); lilywalkers.put(player.getName(), lilies); registerListener(); return true; } private void registerListener() { if (listener == null) { listener = new LilyListener(); registerEvents(listener); } } private void unregisterListener() { if (listener != null && lilywalkers.size() == 0) { unregisterEvents(listener); listener = null; } } public class LilyListener implements Listener { @EventHandler(priority=EventPriority.MONITOR) public void onPlayerMove(PlayerMoveEvent event) { Lilies lilies = lilywalkers.get(event.getPlayer().getName()); if (lilies != null) { Player player = event.getPlayer(); if (isExpired(player)) { turnOff(player); } else { Block block = event.getTo().getBlock(); boolean moved = lilies.isMoved(block); if (moved) { lilies.move(block); addUse(player); chargeUseCost(player); } } } } @EventHandler(priority=EventPriority.NORMAL, ignoreCancelled=true) public void onBlockBreak(BlockBreakEvent event) { if (lilywalkers.size() > 0 && event.getBlock().getType() == Material.WATER_LILY) { for (Lilies lilies : lilywalkers.values()) { if (lilies.contains(event.getBlock())) { event.setCancelled(true); break; } } } } } public class Lilies { private Block center = null; private HashSet<Block> blocks = new HashSet<Block>(); public void move(Block center) { this.center = center; Iterator<Block> iter = blocks.iterator(); while (iter.hasNext()) { Block b = iter.next(); if (!b.equals(center)) { b.setType(Material.AIR); iter.remove(); } } setToLily(center); setToLily(center.getRelative(BlockFace.NORTH)); setToLily(center.getRelative(BlockFace.SOUTH)); setToLily(center.getRelative(BlockFace.EAST)); setToLily(center.getRelative(BlockFace.WEST)); setToLily(center.getRelative(BlockFace.NORTH_WEST)); setToLily(center.getRelative(BlockFace.NORTH_EAST)); setToLily(center.getRelative(BlockFace.SOUTH_WEST)); setToLily(center.getRelative(BlockFace.SOUTH_EAST)); } private void setToLily(Block block) { if (block.getType() == Material.AIR) { BlockState state = block.getRelative(BlockFace.DOWN).getState(); if ((state.getType() == Material.WATER || state.getType() == Material.STATIONARY_WATER) && BlockUtils.getWaterLevel(state) == 0) { block.setType(Material.WATER_LILY); blocks.add(block); } } } public boolean isMoved(Block center) { if (this.center == null || !this.center.equals(center)) { return true; } return false; } public boolean contains(Block block) { return blocks.contains(block); } public void remove() { for (Block block : blocks) { block.setType(Material.AIR); } blocks.clear(); } } public class TeleportListener implements Listener { @EventHandler(priority=EventPriority.MONITOR, ignoreCancelled=true) public void onPlayerTeleport(PlayerTeleportEvent event) { if (lilywalkers.containsKey(event.getPlayer().getName())) { if (!event.getFrom().getWorld().getName().equals(event.getTo().getWorld().getName()) || event.getFrom().toVector().distanceSquared(event.getTo().toVector()) > 50*50) { turnOff(event.getPlayer()); } } } @EventHandler(priority=EventPriority.MONITOR, ignoreCancelled=true) public void onPlayerPortal(PlayerPortalEvent event) { if (lilywalkers.containsKey(event.getPlayer().getName())) { turnOff(event.getPlayer()); } } } @Override public void turnOffBuff(Player player) { Lilies lilies = lilywalkers.remove(player.getName()); if (lilies != null) { lilies.remove(); unregisterListener(); } } @Override protected void turnOff() { for (Lilies lilies : lilywalkers.values()) { lilies.remove(); } lilywalkers.clear(); unregisterListener(); } @Override public boolean isActive(Player player) { return lilywalkers.containsKey(player.getName()); } }