package com.nisovin.magicspells.spells.targeted;
import java.util.HashMap;
import java.util.List;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.Sign;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
import com.nisovin.magicspells.spells.TargetedEntityFromLocationSpell;
import com.nisovin.magicspells.spells.TargetedEntitySpell;
import com.nisovin.magicspells.spells.TargetedSpell;
import com.nisovin.magicspells.util.BlockUtils;
import com.nisovin.magicspells.util.MagicConfig;
public class SummonSpell extends TargetedSpell implements TargetedEntitySpell, TargetedEntityFromLocationSpell {
private boolean requireExactName;
private boolean requireAcceptance;
private int maxAcceptDelay;
private String acceptCommand;
private String strUsage;
private String strSummonPending;
private String strSummonAccepted;
private String strSummonExpired;
private HashMap<Player,Location> pendingSummons;
private HashMap<Player,Long> pendingTimes;
public SummonSpell(MagicConfig config, String spellName) {
super(config, spellName);
requireExactName = getConfigBoolean("require-exact-name", false);
requireAcceptance = getConfigBoolean("require-acceptance", true);
maxAcceptDelay = getConfigInt("max-accept-delay", 90);
acceptCommand = getConfigString("accept-command", "accept");
strUsage = getConfigString("str-usage", "Usage: /cast summon <playername>, or /cast summon \nwhile looking at a sign with a player name on the first line.");
strSummonPending = getConfigString("str-summon-pending", "You are being summoned! Type /accept to teleport.");
strSummonAccepted = getConfigString("str-summon-accepted", "You have been summoned.");
strSummonExpired = getConfigString("str-summon-expired", "The summon has expired.");
if (requireAcceptance) {
pendingSummons = new HashMap<Player,Location>();
pendingTimes = new HashMap<Player,Long>();
}
}
@Override
public PostCastAction castSpell(Player player, SpellCastState state, float power, String[] args) {
if (state == SpellCastState.NORMAL) {
// get target name and landing location
String targetName = "";
Location landLoc = null;
if (args != null && args.length > 0) {
targetName = args[0];
landLoc = player.getLocation().add(0, .25, 0);
} else {
Block block = getTargetedBlock(player, 10);
if (block != null && (block.getType() == Material.WALL_SIGN || block.getType() == Material.SIGN_POST)) {
Sign sign = (Sign)block.getState();
targetName = sign.getLine(0);
landLoc = block.getLocation().add(.5, .25, .5);
}
}
// check usage
if (targetName.equals("")) {
// fail -- show usage
sendMessage(player, strUsage);
return PostCastAction.ALREADY_HANDLED;
}
// check location
if (landLoc == null || !BlockUtils.isSafeToStand(landLoc.clone())) {
sendMessage(player, strUsage);
return PostCastAction.ALREADY_HANDLED;
}
// get player
Player target = null;
if (requireExactName) {
target = Bukkit.getServer().getPlayer(targetName);
if (target != null && !target.getName().equalsIgnoreCase(targetName)) {
target = null;
}
} else {
List<Player> players = Bukkit.getServer().matchPlayer(targetName);
if (players != null && players.size() == 1) {
target = players.get(0);
}
}
if (target == null) {
// fail -- no player target
return noTarget(player);
}
// teleport player
if (requireAcceptance) {
pendingSummons.put(target, landLoc);
pendingTimes.put(target, System.currentTimeMillis());
sendMessage(target, strSummonPending, "%a", player.getDisplayName());
} else {
target.teleport(landLoc);
sendMessage(target, strSummonAccepted, "%a", player.getDisplayName());
}
sendMessages(player, target);
return PostCastAction.NO_MESSAGES;
}
return PostCastAction.HANDLE_NORMALLY;
}
@EventHandler(priority=EventPriority.LOW)
public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent event) {
if (requireAcceptance && event.getMessage().equalsIgnoreCase("/" + acceptCommand) && pendingSummons.containsKey(event.getPlayer())) {
Player player = event.getPlayer();
if (maxAcceptDelay > 0 && pendingTimes.get(player) + maxAcceptDelay*1000 < System.currentTimeMillis()) {
// waited too long
sendMessage(player, strSummonExpired);
} else {
// all ok, teleport
player.teleport(pendingSummons.get(player));
sendMessage(player, strSummonAccepted);
}
pendingSummons.remove(player);
pendingTimes.remove(player);
event.setCancelled(true);
}
}
@Override
public List<String> tabComplete(CommandSender sender, String partial) {
if (partial.contains(" ")) {
return null;
}
return tabCompletePlayerName(sender, partial);
}
@Override
public boolean castAtEntity(Player caster, LivingEntity target, float power) {
return target.teleport(caster);
}
@Override
public boolean castAtEntity(LivingEntity target, float power) {
return false;
}
@Override
public boolean castAtEntityFromLocation(Player caster, Location from, LivingEntity target, float power) {
return target.teleport(from);
}
@Override
public boolean castAtEntityFromLocation(Location from, LivingEntity target, float power) {
return target.teleport(from);
}
}