package net.citizensnpcs.npc; import java.util.List; import java.util.UUID; import org.bukkit.Bukkit; import org.bukkit.World; import org.bukkit.block.Block; import org.bukkit.command.BlockCommandSender; import org.bukkit.command.CommandSender; import org.bukkit.command.ConsoleCommandSender; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.metadata.FixedMetadataValue; import org.bukkit.metadata.MetadataValue; import org.bukkit.metadata.Metadatable; import org.bukkit.plugin.Plugin; import com.google.common.collect.Lists; import net.citizensnpcs.Settings.Setting; import net.citizensnpcs.api.CitizensAPI; import net.citizensnpcs.api.event.CitizensGetSelectedNPCEvent; import net.citizensnpcs.api.event.NPCRemoveEvent; import net.citizensnpcs.api.event.NPCRightClickEvent; import net.citizensnpcs.api.event.NPCSelectEvent; import net.citizensnpcs.api.npc.NPC; import net.citizensnpcs.api.trait.trait.Owner; import net.citizensnpcs.api.util.Messaging; import net.citizensnpcs.editor.Editor; import net.citizensnpcs.util.Util; public class NPCSelector implements Listener, net.citizensnpcs.api.npc.NPCSelector { private UUID consoleSelectedNPC; private final Plugin plugin; public NPCSelector(Plugin plugin) { this.plugin = plugin; Bukkit.getPluginManager().registerEvents(this, plugin); } @Override public void deselect(CommandSender sender) { if (sender instanceof ConsoleCommandSender) { consoleSelectedNPC = null; } else if (sender instanceof Metadatable) { removeMetadata((Metadatable) sender); } } @Override public NPC getSelected(CommandSender sender) { CitizensGetSelectedNPCEvent event = new CitizensGetSelectedNPCEvent(sender); Bukkit.getPluginManager().callEvent(event); if (event.getSelected() != null) return event.getSelected(); if (sender instanceof Player) { return getSelectedFromMetadatable((Player) sender); } else if (sender instanceof BlockCommandSender) { return getSelectedFromMetadatable(((BlockCommandSender) sender).getBlock()); } else if (sender instanceof ConsoleCommandSender) { if (consoleSelectedNPC == null) return null; return CitizensAPI.getNPCRegistry().getByUniqueIdGlobal(consoleSelectedNPC); } return null; } private NPC getSelectedFromMetadatable(Metadatable sender) { List metadata = sender.getMetadata("selected"); if (metadata.size() == 0) return null; if (metadata.get(0).value() == null) { sender.removeMetadata("selected", plugin); return null; } return CitizensAPI.getNPCRegistry().getByUniqueIdGlobal((UUID) metadata.get(0).value()); } @EventHandler private void onNPCRemove(NPCRemoveEvent event) { NPC npc = event.getNPC(); List selectors = npc.data().get("selectors"); if (selectors == null) return; for (String value : selectors) { if (value.equals("console")) { consoleSelectedNPC = null; } else if (value.startsWith("@")) { String[] parts = value.substring(1, value.length()).split(":"); World world = Bukkit.getWorld(parts[0]); if (world != null) { Block block = world.getBlockAt(Integer.parseInt(parts[1]), Integer.parseInt(parts[2]), Integer.parseInt(parts[3])); removeMetadata(block); } } else { removeMetadata(Bukkit.getPlayer(UUID.fromString(value))); } } npc.data().remove("selectors"); } @EventHandler private void onNPCRightClick(NPCRightClickEvent event) { Player player = event.getClicker(); NPC npc = event.getNPC(); List selected = player.getMetadata("selected"); if (selected == null || selected.size() == 0 || selected.get(0).asInt() != npc.getId()) { if (Util.matchesItemInHand(player, Setting.SELECTION_ITEM.asString()) && npc.getOrAddTrait(Owner.class).isOwnedBy(player)) { player.removeMetadata("selected", plugin); select(player, npc); Messaging.sendWithNPC(player, Setting.SELECTION_MESSAGE.asString(), npc); event.setDelayedCancellation(true); } } } private void removeMetadata(Metadatable metadatable) { if (metadatable != null) { metadatable.removeMetadata("selected", plugin); } } @Override public void select(CommandSender sender, NPC npc) { // Remove existing selection if any List selectors = npc.data().get("selectors"); if (selectors == null) { selectors = Lists.newArrayList(); npc.data().set("selectors", selectors); } if (sender instanceof Player) { Player player = (Player) sender; setMetadata(npc, player); selectors.add(player.getUniqueId().toString()); // Remove editor if the player has one Editor.leave(player); } else if (sender instanceof BlockCommandSender) { Block block = ((BlockCommandSender) sender).getBlock(); while (block != null) { setMetadata(npc, block); selectors.add(toName(block)); if (block.getBlockData() instanceof org.bukkit.block.data.Directional) { block = block.getRelative(((org.bukkit.block.data.Directional) block.getBlockData()).getFacing()); if (!block.getType().name().contains("COMMAND_BLOCK")) { block = null; } } else { block = null; } } } else if (sender instanceof ConsoleCommandSender) { consoleSelectedNPC = npc.getUniqueId(); selectors.add("console"); } Bukkit.getPluginManager().callEvent(new NPCSelectEvent(npc, sender)); } private void setMetadata(NPC npc, Metadatable metadatable) { if (metadatable.hasMetadata("selected")) { metadatable.removeMetadata("selected", plugin); } metadatable.setMetadata("selected", new FixedMetadataValue(plugin, npc.getUniqueId())); } private String toName(Block block) { return '@' + block.getWorld().getName() + ":" + Integer.toString(block.getX()) + ":" + Integer.toString(block.getY()) + ":" + Integer.toString(block.getZ()); } }