Solved [1.15.1] Notifying player based on permissions

Discussion in 'Spigot Plugin Development' started by Thinkverse, Jan 7, 2020.

  1. Hi folks.
    I've been playing around with a utility method for notifying players in chat based on permissions, while it works for a single perm node I'm looking for some ideas on how to expand it to somehow work with multiple permission nodes, this is the code I have now, while it works, it seems limited by the fact that it only works with one perm node atm.
    Code (Java):
    public static void notify(CommandSender sender, String permission, String... message) {
      Bukkit.getOnlinePlayers().stream().filter(player -> player.hasPermission(permission)).forEach(player -> {
        /* Don't notify the sender, as we don't wanna send them a msg twice */
        if (player != sender) player.sendMessage(message);
      });
    }

    Util.notify(player, "node.notify", "Some notification"));
     
    Maybe something like this could work? pseudo-code:
    Code (Java):
    public static void notify(CommandSender sender, String message, String[] permission) {
      Bukkit.getOnlinePlayers().forEach(player -> {
        if (Arrays.stream(permission).anyMatch(player::hasPermission)) {
          /* Don't notify the sender, as we don't wanna send them a msg twice */
          if (player != sender) Util.message(player, message);
        }
      });
    }

    Util.notify(player, "Some notification", new String[]{"node.notify", "node.admin"});
     
    Relatively new to Java streams, but done some similar things in other languages before, so I'm thinking I might need some way to map over each player and return those that have a matching node, and then send out the messages, but that won't work since I can't pass any arguments into the map to check, so dual filters?

    I seems to be totally lost right now, anyone willing to point me in some direction?

    Thanks.

    Solution: [1.15.1] Notifying player based on permissions
     
    #1 Thinkverse, Jan 7, 2020
    Last edited: Jan 7, 2020
  2. SteelPhoenix

    Moderator

    Use Stream<T>#filter(Predicate<T>) to filter out all players without said permission
     
  3. I would think the pseudo code would work, try it?
     
  4. Sure, but wouldn't that be just like the first one and only work with one perm node then?
    You're only switching to notifying those without the node instead of those with it.
    Yes, I think that would work too, the only problem though is that you can only send one message to the player using that method, the first one you can send as many as you want in one go.
     
  5. There is no reason why it can't be a vararg of messages tho?
     
  6. SteelPhoenix

    Moderator

    How so?

    Code (Java):
    String[] perms;
    Predicate<? super Player> pred = player -> {
        for (String perm : perms) {
            if (player.hasPermission(perm)) {
                return true;
            }
        }
        return false;
    };
    Also, creating a stream out of an array for each player separately is not efficient.
     
    • Friendly Friendly x 1
  7. I would personally just make a util method for this
     
  8. But then it would be like the first one and only work with one perm node then? Unless I maybe pass in a Map of perm as the second arg maybe?

    Well, I want the method to be as reusable as possible, so I'm passing in both the messages and the perm nodes, and filtering through the online players and notifying only those with a matching node, let's say you have two nodes; node.notify and node.admin, and under some condition, you want to send every player that has at least one matching node some messages, might be one, might be 3, the problems for me seems to be how to pass both the node-set and the messages together.
     
  9. This part, you shouldn't be comparing those objects using !=, instead use !player.equals(sender)
     
  10. Maybe something like this?

    Code (Java):
    public static void notify(CommandSender sender, String[] permission, String... message) {
      Bukkit.getOnlinePlayers().forEach(player -> {
        for (String node : permission) {
          if (player.hasPermission(node) player.sendMessage(message);
        }
      });
    }

    Util.notify(player, new String[]{"node.notify", "node.admin"}, "hello", "player");
     
  11. pseudo-code, it's going in live version.
     
  12. SteelPhoenix

    Moderator

    You'd get duplicate messages if you have both perms - the predicate I provided should just work fine to filter the players.
     
  13. Simpler solution would be to implement a Notification class that has the required permission(s) as attributes along with the message.

    This way you can loop over the notifications and do the permission checks for each notification separately.
     
  14. That seems to work perfectly when testing, doesn't send out duplicate messages even with both nodes active, thanks, now I can expand on that, awesome.
    Code (Java):
    public static void notify(CommandSender sender, String[] permissions, String... message) {
      Bukkit.getOnlinePlayers().stream().filter(player -> {
        for (String node : permissions) {
          if (player.hasPermission(node)) return true;
        }
        return false;
      }).forEach(player -> Util.message(player, message));
    }

    Util.notify(player, new String[]{"node.notify", "node.admin"}, "Notification", "Something happened");