@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)); } } }
@Override public void execute(ScriptEntry scriptEntry) throws CommandExecutionException { // Get objects Action action = (Action) scriptEntry.getObject("action"); dLocation location = (dLocation) scriptEntry.getObject("location"); Element range = (Element) scriptEntry.getObject("range"); Element id = (Element) scriptEntry.getObject("id"); // Report to dB dB.report( scriptEntry, getName(), aH.debugObj("NPC", scriptEntry.getNPC().toString()) + action.name() + id.debug() + (location != null ? location.debug() : "") + (range != null ? range.debug() : "")); dNPC npc = scriptEntry.getNPC(); switch (action) { case ADD: npc.getCitizen().getTrait(Anchors.class).addAnchor(id.asString(), location); return; case ASSUME: npc.getEntity() .teleport( npc.getCitizen().getTrait(Anchors.class).getAnchor(id.asString()).getLocation()); return; case WALKNEAR: npc.getNavigator() .setTarget( Utilities.getWalkableLocationNear( npc.getCitizen().getTrait(Anchors.class).getAnchor(id.asString()).getLocation(), range.asInt())); return; case WALKTO: npc.getNavigator() .setTarget( npc.getCitizen().getTrait(Anchors.class).getAnchor(id.asString()).getLocation()); return; case REMOVE: npc.getCitizen() .getTrait(Anchors.class) .removeAnchor(npc.getCitizen().getTrait(Anchors.class).getAnchor(id.asString())); } }
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); } }
/** * 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); } }
public boolean doAction( String actionName, dNPC npc, dPlayer player, AssignmentScriptContainer assignment, Map<String, dObject> context) { if (assignment == null) { // dB.echoDebug("Tried to do 'on " + actionName + ":' but couldn't find a matching script."); return false; } if (!assignment.contains("actions.on " + actionName)) return false; dB.report( "Action", aH.debugObj("Type", "On " + actionName) + aH.debugObj("NPC", npc.toString()) + assignment.getAsScriptArg().debug() + (player != null ? aH.debugObj("Player", player.getName()) : "")); // Fetch script from Actions List<ScriptEntry> script = assignment.getEntries(player, npc, "actions.on " + actionName); if (script.isEmpty()) return false; dB.echoDebug( DebugElement.Header, "Building action 'On " + actionName.toUpperCase() + "' for " + npc.toString()); // Add entries and context to the queue ScriptQueue queue = InstantQueue.getQueue(null).addEntries(script); if (context != null) { for (Map.Entry<String, dObject> entry : context.entrySet()) { queue.addContext(entry.getKey(), entry.getValue()); } } // Start the queue! queue.start(); // TODO: Read determination to see if the event behind action should be cancelled. return false; }
// Technically defined in TriggerTrait, but placing here instead. // <--[action] // @Actions // chat // // @Triggers when a player chats to the NPC. // // @Context // <context.message> returns the triggering message // <context.keyword> returns the keyword matched by a RegEx trigger // // --> public Boolean process(Player player, String message) { // Check if there is an NPC within range of a player to chat to. dNPC npc = Utilities.getClosestNPC_ChatTrigger(player.getLocation(), 25); dPlayer denizenPlayer = dPlayer.mirrorBukkitPlayer(player); // No NPC? Nothing else to do here. if (npc == null) return false; // If the NPC doesn't have triggers, or the triggers are not enabled, then // just return false. if (!npc.getCitizen().hasTrait(TriggerTrait.class)) return false; if (!npc.getCitizen().getTrait(TriggerTrait.class).isEnabled(name)) return false; // Check range if (npc.getTriggerTrait().getRadius(name) < npc.getLocation().distance(player.getLocation())) return false; // The Denizen config can require some other criteria for a successful chat-with-npc. // Should we check 'line of sight'? Players cannot talk to NPCs through walls // if enabled. Should the Player chat only when looking at the NPC? This may // reduce accidental chats with NPCs. if (Settings.ChatMustSeeNPC()) if (!player.hasLineOfSight(npc.getEntity())) return false; if (Settings.ChatMustLookAtNPC()) if (!Rotation.isFacingEntity(player, npc.getEntity(), 45)) return false; Boolean ret = false; // Denizen should be good to interact with. Let's get the script. InteractScriptContainer script = npc.getInteractScript(denizenPlayer, ChatTrigger.class); Map<String, dObject> context = new HashMap<String, dObject>(); context.put("message", new Element(message)); // If engaged or not cool, calls On Unavailable, if cool, calls On Chat // If available (not engaged, and cool) sets cool down and returns true. if (!npc.getTriggerTrait().trigger(ChatTrigger.this, denizenPlayer, context)) { // If the NPC is not interactable, Settings may allow the chat to filter // through. Check the Settings if this is enabled. if (Settings.ChatGloballyIfUninteractable()) { dB.echoDebug( script, ChatColor.YELLOW + "Resuming. " + ChatColor.WHITE + "The NPC is currently cooling down or engaged."); return false; } else { ret = true; } } // Debugger dB.report( script, name, aH.debugObj("Player", player.getName()) + aH.debugObj("NPC", npc.toString()) + aH.debugObj( "Radius(Max)", npc.getLocation().distance(player.getLocation()) + "(" + npc.getTriggerTrait().getRadius(name) + ")") + aH.debugObj("Trigger text", message) + aH.debugObj("LOS", String.valueOf(player.hasLineOfSight(npc.getEntity()))) + aH.debugObj( "Facing", String.valueOf(Rotation.isFacingEntity(player, npc.getEntity(), 45)))); if (script == null) return false; // Check if the NPC has Chat Triggers for this step. if (!script.containsTriggerInStep( InteractScriptHelper.getCurrentStep(denizenPlayer, script.getName()), ChatTrigger.class)) { // If this is a Chatbot, make it chat anything it wants if // it has no chat triggers for this step if (npc.getCitizen().hasTrait(ChatbotTrait.class)) { Utilities.talkToNPC(message, denizenPlayer, npc, Settings.ChatToNpcOverhearingRange()); npc.getCitizen().getTrait(ChatbotTrait.class).chatTo(player, message); return true; } // No chat trigger for this step.. do we chat globally, or to the NPC? else if (!Settings.ChatGloballyIfNoChatTriggers()) { dB.echoDebug( script, player.getName() + " says to " + npc.getNicknameTrait().getNickname() + ", " + message); return true; } else return ret; } // Parse the script and match Triggers.. if found, cancel the text! The // parser will take care of everything else. String id = null; boolean matched = false; String replacementText = null; String regexId = null; String regexMessage = null; // Use TreeMap to sort chat triggers alphabetically TreeMap<String, String> idMap = new TreeMap<String, String>(); idMap.putAll(script.getIdMapFor(ChatTrigger.class, denizenPlayer)); if (!idMap.isEmpty()) { // Iterate through the different id entries in the step's chat trigger for (Map.Entry<String, String> entry : idMap.entrySet()) { // Check if the chat trigger specified in the specified id's 'trigger:' key // matches the text the player has said String triggerText = TagManager.tag(denizenPlayer, npc, entry.getValue()); Matcher matcher = triggerPattern.matcher(triggerText); while (matcher.find()) { if (!script.checkSpecificTriggerScriptRequirementsFor( ChatTrigger.class, denizenPlayer, npc, entry.getKey())) continue; String keyword = TagManager.tag(denizenPlayer, npc, matcher.group().replace("/", "")); // Check if the trigger is REGEX, but only if we don't have a REGEX // match already (thus using alphabetical priority for triggers) if (regexId == null && isKeywordRegex(keyword)) { Pattern pattern = Pattern.compile(keyword.substring(6)); Matcher m = pattern.matcher(message); if (m.find()) { // REGEX matches are left for last, so save it in case non-REGEX // matches don't exist regexId = entry.getKey(); regexMessage = triggerText.replace(matcher.group(), m.group()); dB.log( "entry value: " + triggerText + " keyword: " + keyword + " m.group: " + m.group() + " matcher.group: " + matcher.group()); context.put("keyword", new Element(m.group())); } } else if (isKeywordStrict(keyword)) { if (message.toUpperCase().equalsIgnoreCase(keyword.toUpperCase())) { // Trigger matches id = entry.getKey(); replacementText = triggerText.replace("/", ""); matched = true; } } else if (message.toUpperCase().contains(keyword.toUpperCase())) { // Trigger matches id = entry.getKey(); replacementText = triggerText.replace("/", ""); matched = true; } } if (matched) break; } } if (!matched && regexId != null) { id = regexId; replacementText = regexMessage; } // If there was a match, the id of the match should have been returned. if (id != null) { Utilities.talkToNPC( replacementText, denizenPlayer, npc, Settings.ChatToNpcOverhearingRange()); parse(npc, denizenPlayer, script, id, context); return true; } else { // If this is a Chatbot, make it chat anything it wants if // none of its chat triggers worked if (npc.getCitizen().hasTrait(ChatbotTrait.class)) { Utilities.talkToNPC(message, denizenPlayer, npc, Settings.ChatToNpcOverhearingRange()); npc.getCitizen().getTrait(ChatbotTrait.class).chatTo(player, message); return true; } else if (!Settings.ChatGloballyIfFailedChatTriggers()) { Utilities.talkToNPC(message, denizenPlayer, npc, Settings.ChatToNpcOverhearingRange()); return true; } // No matching chat triggers, and the config.yml says we // should just ignore the interaction... } return ret; }
public boolean execute(ScriptEntry scriptEntry) { Matcher m; StringBuffer sb; if (scriptEntry.getCommandName().indexOf('%') != -1) { m = definition_pattern.matcher(scriptEntry.getCommandName()); sb = new StringBuffer(); while (m.find()) { String definition = scriptEntry.getResidingQueue().getDefinition(m.group(1)); if (definition == null) definition = "null"; m.appendReplacement(sb, definition); } m.appendTail(sb); scriptEntry.setCommandName(sb.toString()); } // Get the command instance ready for the execution of the scriptEntry AbstractCommand command = plugin.getCommandRegistry().get(scriptEntry.getCommandName()); if (command == null) { dB.echoDebug( scriptEntry, DebugElement.Header, "Executing command: " + scriptEntry.getCommandName()); dB.echoError( scriptEntry.getCommandName() + " is an invalid dCommand! Are you sure it loaded?"); dB.echoDebug(scriptEntry, DebugElement.Footer); return false; } // Debugger information if (scriptEntry.getPlayer() != null) dB.echoDebug( scriptEntry, DebugElement.Header, "Executing dCommand: " + scriptEntry.getCommandName() + "/" + scriptEntry.getPlayer().getName()); else dB.echoDebug( scriptEntry, DebugElement.Header, "Executing dCommand: " + scriptEntry.getCommandName() + (scriptEntry.getNPC() != null ? "/" + scriptEntry.getNPC().getName() : "")); // Don't execute() if problems arise in parseArgs() boolean keepGoing = true; try { // Throw exception if arguments are required for this command, but not supplied. if (command.getOptions().REQUIRED_ARGS > scriptEntry.getArguments().size()) throw new InvalidArgumentsException(""); if (scriptEntry.has_tags) scriptEntry.setArguments( TagManager.fillArguments( scriptEntry.getArguments(), scriptEntry, true)); // Replace tags /* If using NPC:# or PLAYER:Name arguments, these need to be changed out immediately because... * 1) Denizen/Player flags need the desired NPC/PLAYER before parseArgs's getFilledArguments() so that * the Player/Denizen flags will read from the correct Object. If using PLAYER or NPCID arguments, * the desired Objects are obviously not the same objects that were sent with the ScriptEntry. * 2) These arguments should be valid for EVERY ScriptCommand, so why not just take care of it * here, instead of requiring each command to take care of the argument. */ List<String> newArgs = new ArrayList<String>(); // Don't fill in tags if there were brackets detected.. // This means we're probably in a nested if. int nested_depth = 0; // Watch for IF command to avoid filling player and npc arguments // prematurely boolean if_ignore = false; for (aH.Argument arg : aH.interpret(scriptEntry.getArguments())) { if (arg.getValue().equals("{")) nested_depth++; if (arg.getValue().equals("}")) nested_depth--; // If nested, continue. if (nested_depth > 0) { newArgs.add(arg.raw_value); continue; } if (arg.raw_value.indexOf('%') != -1) { m = definition_pattern.matcher(arg.raw_value); sb = new StringBuffer(); while (m.find()) { String definition = scriptEntry.getResidingQueue().getDefinition(m.group(1)); if (definition == null) definition = "null"; m.appendReplacement(sb, definition); } m.appendTail(sb); arg = aH.Argument.valueOf(sb.toString()); } // If using IF, check if we've reached the command + args // so that we don't fill player: or npc: prematurely if (command.getName().equalsIgnoreCase("if") && DenizenAPI.getCurrentInstance().getCommandRegistry().get(arg.getValue()) != null) if_ignore = true; // Fill player/off-line player if (arg.matchesPrefix("player") && !if_ignore) { dB.echoDebug(scriptEntry, "...replacing the linked player with " + arg.getValue()); String value = TagManager.tag( scriptEntry.getPlayer(), scriptEntry.getNPC(), arg.getValue(), false, scriptEntry); dPlayer player = dPlayer.valueOf(value); if (player == null || !player.isValid()) { dB.echoError(value + " is an invalid player!"); return false; } scriptEntry.setPlayer(player); } // Fill NPCID/NPC argument else if (arg.matchesPrefix("npc, npcid") && !if_ignore) { dB.echoDebug(scriptEntry, "...replacing the linked NPC with " + arg.getValue()); String value = TagManager.tag( scriptEntry.getPlayer(), scriptEntry.getNPC(), arg.getValue(), false, scriptEntry); dNPC npc = dNPC.valueOf(value); if (npc == null || !npc.isValid()) { dB.echoError(value + " is an invalid NPC!"); return false; } scriptEntry.setNPC(npc); } // Save the scriptentry if needed later for fetching scriptentry context else if (arg.matchesPrefix("save") && !if_ignore) { dB.echoDebug(scriptEntry, "...remembering this script entry!"); scriptEntry.getResidingQueue().holdScriptEntry(arg.getValue(), scriptEntry); } else newArgs.add(arg.raw_value); } // Add the arguments back to the scriptEntry. scriptEntry.setArguments(newArgs); // Now process non-instant tags. if (scriptEntry.has_tags) scriptEntry.setArguments( TagManager.fillArguments(scriptEntry.getArguments(), scriptEntry, false)); // Parse the rest of the arguments for execution. command.parseArgs(scriptEntry); } catch (InvalidArgumentsException e) { keepGoing = false; // Give usage hint if InvalidArgumentsException was called. dB.echoError("Woah! Invalid arguments were specified!"); if (e.getMessage() != null && e.getMessage().length() > 0) dB.log( ChatColor.YELLOW + "+> MESSAGE follows: " + ChatColor.WHITE + "'" + e.getMessage() + "'"); dB.log("Usage: " + command.getUsageHint()); dB.echoDebug(scriptEntry, DebugElement.Footer); scriptEntry.setFinished(true); } catch (Exception e) { keepGoing = false; dB.echoError("Woah! An exception has been called with this command!"); dB.echoError(e); dB.echoDebug(scriptEntry, DebugElement.Footer); scriptEntry.setFinished(true); } finally { if (keepGoing) try { // Run the execute method in the command command.execute(scriptEntry); } catch (Exception e) { dB.echoError("Woah!! An exception has been called with this command!"); dB.echoError(e); scriptEntry.setFinished(true); } } return true; }