Ejemplo n.º 1
0
 @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));
     }
   }
 }
Ejemplo n.º 2
0
  @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()));
    }
  }
Ejemplo n.º 3
0
 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);
   }
 }
Ejemplo n.º 4
0
  /**
   * 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);
    }
  }
Ejemplo n.º 5
0
  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;
  }
Ejemplo n.º 6
0
  // 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;
  }
Ejemplo n.º 7
0
  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;
  }