package net.aufdemrand.denizen.npc; import net.aufdemrand.denizen.BukkitScriptEntryData; import net.aufdemrand.denizen.Denizen; import net.aufdemrand.denizen.flags.FlagManager; import net.aufdemrand.denizen.npc.actions.ActionHandler; import net.aufdemrand.denizen.objects.dNPC; import net.aufdemrand.denizen.utilities.DenizenAPI; import net.aufdemrand.denizen.utilities.debugging.dB; import net.aufdemrand.denizen.utilities.depends.Depends; import net.aufdemrand.denizencore.events.OldEventManager; import net.citizensnpcs.api.CitizensAPI; import net.citizensnpcs.api.event.NPCDespawnEvent; import net.citizensnpcs.api.event.NPCRemoveEvent; import net.citizensnpcs.api.event.NPCSpawnEvent; import net.citizensnpcs.api.npc.NPC; import net.citizensnpcs.api.trait.trait.Equipment; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryType; import org.bukkit.inventory.Inventory; import java.util.*; import java.util.concurrent.ConcurrentHashMap; /** * Used for keeping track and retrieving dNPC objects which offer some Denizen-specific * methods when dealing with NPCs. * * @author Jeremy Schroeder */ public class dNPCRegistry implements Listener { private static Map<Integer, dNPC> denizenNPCs = new ConcurrentHashMap<Integer, dNPC>(8, 0.9f, 1); private static Map<Integer, Inventory> npcInventories = new ConcurrentHashMap<Integer, Inventory>(8, 0.9f, 1); public static dNPCRegistry getCurrentInstance() { return DenizenAPI.getCurrentInstance().getNPCRegistry(); } private Denizen plugin; private ActionHandler actionHandler; public dNPCRegistry(Denizen denizen) { plugin = denizen; if (Depends.citizens != null) { plugin.getServer().getPluginManager().registerEvents(this, plugin); } actionHandler = new ActionHandler(plugin); } /** * Gets the currently loaded instance of the ActionHandler * * @return ActionHandler */ public ActionHandler getActionHandler() { return actionHandler; } public static boolean _isRegistered(NPC npc) { return denizenNPCs.containsKey(npc.getId()); } public static boolean _isRegistered(int id) { return denizenNPCs.containsKey(id); } public static void _registerNPC(dNPC denizenNPC) { if (denizenNPC == null || !denizenNPC.isValid()) { return; } int id = denizenNPC.getId(); if (!denizenNPCs.containsKey(id)) { denizenNPCs.put(id, denizenNPC); Inventory npcInventory = Bukkit.getServer().createInventory(denizenNPC, InventoryType.PLAYER); npcInventory.setContents(Arrays.copyOf(denizenNPC.getInventoryTrait().getContents(), npcInventory.getSize())); npcInventories.put(id, npcInventory); } } private static void _registerNPC(NPC npc) { if (npc == null) { return; } if (!denizenNPCs.containsKey(npc.getId())) { _registerNPC(new dNPC(npc)); } } /** * Returns a dNPC object when given a valid NPC. DenizenNPCs have some methods * specific to Denizen functionality as well as easy access to the attached NPC and LivingEntity. * * @param npc the Citizens NPC * @return a dNPC */ public static dNPC getDenizen(NPC npc) { return new dNPC(npc); } public static dNPC getDenizen(int id) { return new dNPC(CitizensAPI.getNPCRegistry().getById(id)); } /** * Returns a dInventory object from the Inventory trait of a valid NPC. * * @param npc the Citizens NPC * @return the NPC's dInventory */ public static Inventory getInventory(NPC npc) { if (npc == null) { return null; } if (!npcInventories.containsKey(npc.getId())) { _registerNPC(npc); } return npcInventories.get(npc.getId()); } /** * Similar to getting NPCs from Citizens' NPCRegistry, but this will filter out * unspawned NPCs * * @return map of NPC, dNPC of all spawned NPCs */ public static Set<dNPC> getSpawnedNPCs() { Iterator<Map.Entry<Integer, dNPC>> it = denizenNPCs.entrySet().iterator(); Set<dNPC> npcs = new HashSet<dNPC>(); while (it.hasNext()) { Map.Entry<Integer, dNPC> npc = it.next(); if (npc.getValue().getCitizen() == null) { try { denizenNPCs.remove(npc.getKey()); } catch (Exception e) { dB.echoError("Report this error to the Denizen team! Err: posconcurrency1"); } } else if (npc.getValue().isSpawned()) { npcs.add(npc.getValue()); } } return npcs; } // <--[action] // @Actions // spawn // @Triggers when the NPC is spawned. // This will fire whenever an NPC's chunk is loaded, or a spawn command is issued. // // @Context // None // --> /** * Fires the 'On Spawn:' action in an NPCs Assignment, if set. * * @param event NPCSpawnEvent */ @EventHandler public void onSpawn(NPCSpawnEvent event) { if (event.getNPC() == null) { dB.echoError("Null NPC spawned!"); return; } _registerNPC(event.getNPC()); // Do world script event 'On NPC spawns' OldEventManager.doEvents(Arrays.asList ("npc spawns"), new BukkitScriptEntryData(null, dNPC.mirrorCitizensNPC(event.getNPC())), null); // On Spawn action new dNPC(event.getNPC()).action("spawn", null); } // <--[action] // @Actions // despawn // @Triggers when the NPC is despawned. // This can be because a command was issued, or a chunk has been unloaded. // // @Context // None // --> /** * Fires a world script event and then NPC action when the NPC despawns. * * @param event NPCDespawnEvent */ @EventHandler public void despawn(NPCDespawnEvent event) { dNPC npc = getDenizen(event.getNPC().getId()); // Do world script event 'On NPC Despawns' if (npc != null) { OldEventManager.doEvents(Arrays.asList("npc despawns"), new BukkitScriptEntryData(null, npc), null); } if (npc != null) { npc.action("despawn", null); } } // <--[action] // @Actions // remove // @Triggers when the NPC is removed. // // @Context // None // --> /** * Removes an NPC from the Registry when removed from Citizens. * * @param event NPCRemoveEvent */ @EventHandler public void onRemove(NPCRemoveEvent event) { NPC npc = event.getNPC(); getDenizen(npc).action("remove", null); if (_isRegistered(npc)) { denizenNPCs.remove(npc.getId()); npcInventories.remove(npc.getId()); } FlagManager.clearNPCFlags(npc.getId()); } @EventHandler public void onInventoryClick(InventoryClickEvent event) { Inventory inventory = event.getInventory(); if (inventory.getHolder() instanceof dNPC) { dNPC npc = (dNPC) inventory.getHolder(); npc.getInventory().setContents(inventory.getContents()); Equipment equipment = npc.getEquipmentTrait(); for (int i = 0; i < 5; i++) { equipment.set(i, inventory.getItem(i)); } } } }