package com.nisovin.magicspells.spells.buff;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.bukkit.Bukkit;
import org.bukkit.Effect;
import org.bukkit.GameMode;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.block.Action;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.inventory.ItemStack;
import com.nisovin.magicspells.MagicSpells;
import com.nisovin.magicspells.materials.MagicMaterial;
import com.nisovin.magicspells.spells.BuffSpell;
import com.nisovin.magicspells.util.MagicConfig;
public class ReachSpell extends BuffSpell {
private int range;
private boolean consumeBlocks;
private boolean dropBlocks;
private Set<Material> disallowedBreakBlocks;
private Set<Material> disallowedPlaceBlocks;
private HashSet<String> reaching;
public ReachSpell(MagicConfig config, String spellName) {
super(config, spellName);
range = getConfigInt("range", 15);
consumeBlocks = getConfigBoolean("consume-blocks", true);
dropBlocks = getConfigBoolean("drop-blocks", true);
disallowedBreakBlocks = EnumSet.noneOf(Material.class);
List<String> list = getConfigStringList("disallowed-break-blocks", null);
if (list != null) {
for (String s : list) {
MagicMaterial m = MagicSpells.getItemNameResolver().resolveBlock(s);
if (m != null && m.getMaterial() != null) {
disallowedBreakBlocks.add(m.getMaterial());
}
}
}
disallowedPlaceBlocks = EnumSet.noneOf(Material.class);
list = getConfigStringList("disallowed-place-blocks", null);
if (list != null) {
for (String s : list) {
MagicMaterial m = MagicSpells.getItemNameResolver().resolveBlock(s);
if (m != null && m.getMaterial() != null) {
disallowedPlaceBlocks.add(m.getMaterial());
}
}
}
reaching = new HashSet<String>();
}
@Override
public boolean castBuff(Player player, float power, String[] args) {
reaching.add(player.getName());
return true;
}
@EventHandler(priority=EventPriority.HIGHEST)
public void onPlayerInteract(PlayerInteractEvent event) {
if (isActive(event.getPlayer())) {
Player player = event.getPlayer();
// check expired
if (isExpired(player)) {
turnOff(player);
return;
}
// get targeted block
Action action = event.getAction();
List<Block> targets = getLastTwoTargetedBlocks(player, range);
Block airBlock, targetBlock;
if (targets != null && targets.size() == 2) {
airBlock = targets.get(0);
targetBlock = targets.get(1);
if ((action == Action.LEFT_CLICK_AIR || action == Action.LEFT_CLICK_BLOCK) && targetBlock.getType() != Material.AIR) {
// break
// check for disallowed
if (disallowedBreakBlocks.contains(targetBlock.getType())) {
return;
}
// call break event
BlockBreakEvent evt = new BlockBreakEvent(targetBlock, player);
Bukkit.getPluginManager().callEvent(evt);
if (!evt.isCancelled()) {
// remove block
targetBlock.getWorld().playEffect(targetBlock.getLocation(), Effect.STEP_SOUND, targetBlock.getType());
// drop item
if (dropBlocks && player.getGameMode() == GameMode.SURVIVAL) {
targetBlock.breakNaturally();
} else {
targetBlock.setType(Material.AIR);
}
addUseAndChargeCost(player);
}
} else if ((action == Action.RIGHT_CLICK_AIR || action == Action.RIGHT_CLICK_BLOCK) && targetBlock.getType() != Material.AIR) {
// place
// check for block in hand
ItemStack inHand = player.getItemInHand();
if (inHand != null && inHand.getType() != Material.AIR && inHand.getType().isBlock()) {
// check for disallowed
if (disallowedPlaceBlocks.contains(inHand.getType())) {
return;
}
BlockState prevState = airBlock.getState();
// place block
BlockState state = airBlock.getState();
state.setType(inHand.getType());
state.setData(inHand.getData());
state.update(true);
// call event
BlockPlaceEvent evt = new BlockPlaceEvent(airBlock, prevState, targetBlock, inHand, player, true);
Bukkit.getPluginManager().callEvent(evt);
if (evt.isCancelled()) {
// cancelled, revert
prevState.update(true);
} else {
// remove item from hand
if (consumeBlocks && player.getGameMode() != GameMode.CREATIVE) {
if (inHand.getAmount() > 1) {
inHand.setAmount(inHand.getAmount() - 1);
player.setItemInHand(inHand);
} else {
player.setItemInHand(null);
}
}
addUseAndChargeCost(player);
event.setCancelled(true);
}
}
}
}
}
}
@Override
public void turnOffBuff(Player player) {
reaching.remove(player.getName());
}
@Override
protected void turnOff() {
reaching.clear();
}
@Override
public boolean isActive(Player player) {
return reaching.contains(player.getName());
}
}