diff --git a/LICENSE.txt b/LICENSE.txt index 3c9e505..8b4bf01 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,6 +1,7 @@ -MIT License +The MIT License. -Copyright (c) 2016 Lucko (Luck) +Copyright (c) lucko (Luck) +Copyright (c) contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 409a2a9..15e4570 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,12 @@ # LuckPermsPlaceholders [![Build Status](https://ci.lucko.me/job/LuckPermsPlaceholders/badge/icon)](https://ci.lucko.me/job/LuckPermsPlaceholders/) -PlaceholderAPI Expansion for LuckPerms +Provides LuckPerms placeholders for PlaceholderAPI and MVdWPlaceholderAPI ## Downloads -You can get the latest version [here](https://ci.lucko.me/job/LuckPermsPlaceholders/). +You can get the latest versions [here](https://ci.lucko.me/job/LuckPermsPlaceholders/). ## Installation -You just need to place `Expansion-LuckPerms.jar` from the download page above in the PlaceholderAPI expansions folder, located at `/plugins/PlaceholderAPI/expansions/`. +### PlaceholderAPI +You need to place `Expansion-LuckPerms.jar` from the download page above in the PlaceholderAPI expansions folder, located at `/plugins/PlaceholderAPI/expansions/`. + +### MVdWPlaceholderAPI +You need to place `LuckPermsMVdWHook.jar` in your plugins folder. diff --git a/luckperms-mvdw-hook/pom.xml b/luckperms-mvdw-hook/pom.xml new file mode 100644 index 0000000..dadbe39 --- /dev/null +++ b/luckperms-mvdw-hook/pom.xml @@ -0,0 +1,50 @@ + + + 4.0.0 + + + me.lucko + luckperms-placeholders-parent + 3.3-SNAPSHOT + + + luckperms-mvdw-hook + jar + + + UTF-8 + + + + clean package + LuckPermsMVdWHook + + + true + src/main/resources + + *.yml + + + + + + + + + be.maximvdw + MVdWPlaceholderAPI + 1.0.2-SNAPSHOT + + + + + + mvdw-software + http://repo.mvdw-software.be/content/groups/public/ + + + + \ No newline at end of file diff --git a/luckperms-mvdw-hook/src/main/java/me/lucko/luckperms/placeholders/LuckPermsMVdWHook.java b/luckperms-mvdw-hook/src/main/java/me/lucko/luckperms/placeholders/LuckPermsMVdWHook.java new file mode 100644 index 0000000..d812f1a --- /dev/null +++ b/luckperms-mvdw-hook/src/main/java/me/lucko/luckperms/placeholders/LuckPermsMVdWHook.java @@ -0,0 +1,298 @@ +/* + * This file is part of LuckPerms, licensed under the MIT License. + * + * Copyright (c) lucko (Luck) + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package me.lucko.luckperms.placeholders; + +import com.google.common.base.Splitter; +import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; + +import me.lucko.luckperms.api.Contexts; +import me.lucko.luckperms.api.Group; +import me.lucko.luckperms.api.LuckPermsApi; +import me.lucko.luckperms.api.Node; +import me.lucko.luckperms.api.Track; +import me.lucko.luckperms.api.User; +import me.lucko.luckperms.api.caching.PermissionData; +import me.lucko.luckperms.api.caching.UserData; + +import org.bukkit.entity.Player; +import org.bukkit.plugin.java.JavaPlugin; + +import be.maximvdw.placeholderapi.PlaceholderAPI; +import be.maximvdw.placeholderapi.PlaceholderReplaceEvent; +import be.maximvdw.placeholderapi.PlaceholderReplacer; + +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +/** + * MVdWPlaceholderAPI Hook for LuckPerms, implemented using the LuckPerms API. + */ +public class LuckPermsMVdWHook extends JavaPlugin implements PlaceholderReplacer { + + private LuckPermsApi api; + + @Override + public void onEnable() { + if (!getServer().getServicesManager().isProvidedFor(LuckPermsApi.class)) { + throw new RuntimeException("LuckPermsApi not provided."); + } + + api = getServer().getServicesManager().load(LuckPermsApi.class); + PlaceholderAPI.registerPlaceholder(this, "luckperms_*", this); + } + + private Contexts makeContexts(User user) { + Contexts contexts = api.getContextForUser(user).orElse(null); + if (contexts == null) { + contexts = Contexts.allowAll(); + } + return contexts; + } + + @Override + public String onPlaceholderReplace(PlaceholderReplaceEvent event) { + String placeholder = event.getPlaceholder(); + if (!placeholder.startsWith("luckperms_")) { + return null; + } + + String identifier = placeholder.substring("luckperms_".length()).toLowerCase(); + Player player = event.getPlayer(); + + if (player == null || api == null) { + return ""; + } + + User user = api.getUserSafe(api.getUuidCache().getUUID(player.getUniqueId())).orElse(null); + if (user == null) { + return ""; + } + + UserData data = user.getCachedData(); + identifier = identifier.toLowerCase(); + + if (identifier.equals("group_name")) { + return user.getPrimaryGroup(); + } + + if (identifier.startsWith("context_") && identifier.length() > "context_".length()) { + String key = identifier.substring("context_".length()); + return api.getContextForUser(user) + .map(Contexts::getContexts) + .map(c -> c.getValues(key)) + .map(s -> Iterables.getFirst(s, "")) + .orElse(""); + } + + if (identifier.equals("groups")) { + return user.getOwnNodes().stream().filter(Node::isGroupNode).map(Node::getGroupName).collect(Collectors.joining(", ")); + } + + if (identifier.startsWith("has_permission_") && identifier.length() > "has_permission_".length()) { + String node = identifier.substring("has_permission_".length()); + return formatBoolean(user.hasPermission(api.buildNode(node).build()).asBoolean()); + } + + if (identifier.startsWith("inherits_permission_") && identifier.length() > "inherits_permission_".length()) { + String node = identifier.substring("inherits_permission_".length()); + return formatBoolean(data.getPermissionData(makeContexts(user)).getPermissionValue(node).asBoolean()); + } + + if (identifier.startsWith("check_permission_") && identifier.length() > "check_permission_".length()) { + String node = identifier.substring("check_permission_".length()); + return formatBoolean(data.getPermissionData(makeContexts(user)).getPermissionValue(node).asBoolean()); + } + + if (identifier.startsWith("in_group_") && identifier.length() > "in_group_".length()) { + String groupName = identifier.substring("in_group_".length()); + return formatBoolean(user.getOwnNodes().stream().filter(Node::isGroupNode).map(Node::getGroupName).anyMatch(s -> s.equalsIgnoreCase(groupName))); + } + + if (identifier.startsWith("inherits_group_") && identifier.length() > "inherits_group_".length()) { + String groupName = identifier.substring("inherits_group_".length()); + return formatBoolean(data.getPermissionData(makeContexts(user)).getPermissionValue("group." + groupName).asBoolean()); + } + + if (identifier.startsWith("on_track_") && identifier.length() > "on_track_".length()) { + String trackName = identifier.substring("on_track_".length()); + return api.getTrackSafe(trackName) + .map(t -> formatBoolean(t.containsGroup(user.getPrimaryGroup()))) + .orElse(""); + } + + if (identifier.startsWith("has_groups_on_track_") && identifier.length() > "has_groups_on_track_".length()) { + String trackName = identifier.substring("has_groups_on_track_".length()); + return api.getTrackSafe(trackName).map(t -> { + boolean match = user.getOwnNodes().stream().filter(Node::isGroupNode).map(Node::getGroupName).anyMatch(t::containsGroup); + return formatBoolean(match); + }).orElse(""); + } + + if (identifier.equals("highest_group_by_weight")) { + return user.getPermissions().stream() + .filter(Node::isGroupNode) + .map(Node::getGroupName) + .map(s -> api.getGroupSafe(s)) + .filter(Optional::isPresent) + .map(Optional::get) + .sorted((o1, o2) -> { + int ret = Integer.compare(o1.getWeight().orElse(0), o2.getWeight().orElse(0)); + return ret == 1 ? 1 : -1; + }) + .findFirst() + .map(Group::getName) + .orElse(""); + } + + if (identifier.equals("lowest_group_by_weight")) { + return user.getPermissions().stream() + .filter(Node::isGroupNode) + .map(Node::getGroupName) + .map(s -> api.getGroupSafe(s)) + .filter(Optional::isPresent) + .map(Optional::get) + .sorted((o1, o2) -> { + int ret = Integer.compare(o1.getWeight().orElse(0), o2.getWeight().orElse(0)); + return ret == 1 ? -1 : 1; + }) + .findFirst() + .map(Group::getName) + .orElse(""); + } + + if (identifier.startsWith("first_group_on_tracks_") && identifier.length() > "first_group_on_tracks_".length()) { + List tracks = Splitter.on(',').trimResults().splitToList(identifier.substring("first_group_on_tracks_".length())); + PermissionData permData = data.getPermissionData(makeContexts(user)); + return tracks.stream() + .map(t -> api.getTrackSafe(t)) + .filter(Optional::isPresent) + .map(Optional::get) + .map(Track::getGroups) + .map(groups -> groups.stream() + .filter(s -> permData.getPermissionValue("group." + s).asBoolean()) + .findFirst() + ) + .filter(Optional::isPresent) + .map(Optional::get) + .findFirst() + .orElse(""); + } + + if (identifier.startsWith("last_group_on_tracks_") && identifier.length() > "last_group_on_tracks_".length()) { + List tracks = Splitter.on(',').trimResults().splitToList(identifier.substring("last_group_on_tracks_".length())); + PermissionData permData = data.getPermissionData(makeContexts(user)); + return tracks.stream() + .map(t -> api.getTrackSafe(t)) + .filter(Optional::isPresent) + .map(Optional::get) + .map(Track::getGroups) + .map(Lists::reverse) + .map(groups -> groups.stream() + .filter(s -> permData.getPermissionValue("group." + s).asBoolean()) + .findFirst() + ) + .filter(Optional::isPresent) + .map(Optional::get) + .findFirst() + .orElse(""); + } + + if (identifier.startsWith("expiry_time_") && identifier.length() > "expiry_time_".length()) { + String node = identifier.substring("expiry_time_".length()); + long currentTime = System.currentTimeMillis() / 1000L; + return user.getPermissions().stream() + .filter(Node::isTemporary) + .filter(n -> n.getPermission().equals(node)) + .map(Node::getExpiryUnixTime) + .findAny() + .map(e -> getTime((int) (e - currentTime))) + .orElse(""); + } + + if (identifier.startsWith("group_expiry_time_") && identifier.length() > "group_expiry_time_".length()) { + String group = identifier.substring("group_expiry_time_".length()); + long currentTime = System.currentTimeMillis() / 1000L; + return user.getPermissions().stream() + .filter(Node::isTemporary) + .filter(Node::isGroupNode) + .filter(n -> n.getGroupName().equals(group)) + .map(Node::getExpiryUnixTime) + .findAny() + .map(e -> getTime((int) (e - currentTime))) + .orElse(""); + } + + if (identifier.equalsIgnoreCase("prefix")) { + return Optional.ofNullable(data.calculateMeta(makeContexts(user)).getPrefix()).orElse(""); + } + + if (identifier.equalsIgnoreCase("suffix")) { + return Optional.ofNullable(data.calculateMeta(makeContexts(user)).getSuffix()).orElse(""); + } + + if (identifier.startsWith("meta_") && identifier.length() > "meta_".length()) { + String node = identifier.substring("meta_".length()); + return data.getMetaData(makeContexts(user)).getMeta().getOrDefault(node, ""); + } + + return null; + } + + private static String formatBoolean(boolean b) { + return b ? "yes" : "no"; + } + + private static String getTime(int seconds) { + if (seconds == 0) { + return "0s"; + } + + long minute = seconds / 60; + seconds = seconds % 60; + long hour = minute / 60; + minute = minute % 60; + long day = hour / 24; + hour = hour % 24; + + StringBuilder time = new StringBuilder(); + if (day != 0) { + time.append(day).append("d "); + } + if (hour != 0) { + time.append(hour).append("h "); + } + if (minute != 0) { + time.append(minute).append("m "); + } + if (seconds != 0) { + time.append(seconds).append("s"); + } + + return time.toString().trim(); + } +} diff --git a/luckperms-mvdw-hook/src/main/resources/plugin.yml b/luckperms-mvdw-hook/src/main/resources/plugin.yml new file mode 100644 index 0000000..6cfb2f1 --- /dev/null +++ b/luckperms-mvdw-hook/src/main/resources/plugin.yml @@ -0,0 +1,7 @@ +name: LuckPermsMVdWHook +version: ${project.version} +description: Provides placeholders for LuckPerms +author: Luck +website: https://github.com/lucko/LuckPerms/wiki/Placeholders +main: me.lucko.luckperms.placeholders.LuckPermsMVdWHook +depend: [LuckPerms, MVdWPlaceholderAPI] \ No newline at end of file diff --git a/luckperms-papi-expansion/pom.xml b/luckperms-papi-expansion/pom.xml new file mode 100644 index 0000000..337618e --- /dev/null +++ b/luckperms-papi-expansion/pom.xml @@ -0,0 +1,42 @@ + + + 4.0.0 + + + me.lucko + luckperms-placeholders-parent + 3.3-SNAPSHOT + + + luckperms-papi-expansion + jar + + + UTF-8 + + + + clean package + Expansion-LuckPerms + + + + + + me.clip + placeholderapi + 2.8.2 + provided + + + + + + placeholderapi-repo + http://repo.extendedclip.com/content/repositories/placeholderapi/ + + + + \ No newline at end of file diff --git a/src/main/java/me/lucko/luckperms/placeholders/LuckPermsExpansion.java b/luckperms-papi-expansion/src/main/java/me/lucko/luckperms/placeholders/LuckPermsExpansion.java similarity index 94% rename from src/main/java/me/lucko/luckperms/placeholders/LuckPermsExpansion.java rename to luckperms-papi-expansion/src/main/java/me/lucko/luckperms/placeholders/LuckPermsExpansion.java index 20a29fb..05e2dea 100644 --- a/src/main/java/me/lucko/luckperms/placeholders/LuckPermsExpansion.java +++ b/luckperms-papi-expansion/src/main/java/me/lucko/luckperms/placeholders/LuckPermsExpansion.java @@ -1,5 +1,8 @@ /* - * Copyright (c) 2016 Lucko (Luck) + * This file is part of LuckPerms, licensed under the MIT License. + * + * Copyright (c) lucko (Luck) + * Copyright (c) contributors * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -45,14 +48,14 @@ import java.util.List; import java.util.Optional; import java.util.stream.Collectors; -/* +/** * PlaceholderAPI Expansion for LuckPerms, implemented using the LuckPerms API. */ public class LuckPermsExpansion extends PlaceholderExpansion { private static final String IDENTIFIER = "luckperms"; private static final String PLUGIN_NAME = "LuckPerms"; private static final String AUTHOR = "Luck"; - private static final String VERSION = "3.0-R3"; + private static final String VERSION = "3.3-R1"; private LuckPermsApi api = null; @@ -90,11 +93,7 @@ public class LuckPermsExpansion extends PlaceholderExpansion { return ""; } - UserData data = user.getUserDataCache().orElse(null); - if (data == null) { - return ""; - } - + UserData data = user.getCachedData(); identifier = identifier.toLowerCase(); if (identifier.equals("group_name")) { @@ -111,7 +110,7 @@ public class LuckPermsExpansion extends PlaceholderExpansion { } if (identifier.equals("groups")) { - return user.getGroupNames().stream().collect(Collectors.joining(", ")); + return user.getOwnNodes().stream().filter(Node::isGroupNode).map(Node::getGroupName).collect(Collectors.joining(", ")); } if (identifier.startsWith("has_permission_") && identifier.length() > "has_permission_".length()) { @@ -131,7 +130,7 @@ public class LuckPermsExpansion extends PlaceholderExpansion { if (identifier.startsWith("in_group_") && identifier.length() > "in_group_".length()) { String groupName = identifier.substring("in_group_".length()); - return formatBoolean(user.getGroupNames().contains(groupName)); + return formatBoolean(user.getOwnNodes().stream().filter(Node::isGroupNode).map(Node::getGroupName).anyMatch(s -> s.equalsIgnoreCase(groupName))); } if (identifier.startsWith("inherits_group_") && identifier.length() > "inherits_group_".length()) { @@ -149,12 +148,8 @@ public class LuckPermsExpansion extends PlaceholderExpansion { if (identifier.startsWith("has_groups_on_track_") && identifier.length() > "has_groups_on_track_".length()) { String trackName = identifier.substring("has_groups_on_track_".length()); return api.getTrackSafe(trackName).map(t -> { - for (String group : user.getGroupNames()) { - if (t.containsGroup(group)) { - return formatBoolean(true); - } - } - return formatBoolean(false); + boolean match = user.getOwnNodes().stream().filter(Node::isGroupNode).map(Node::getGroupName).anyMatch(t::containsGroup); + return formatBoolean(match); }).orElse(""); } diff --git a/pom.xml b/pom.xml index 4e0f524..80e6ef0 100644 --- a/pom.xml +++ b/pom.xml @@ -5,12 +5,16 @@ 4.0.0 me.lucko - luckperms-placeholders - 3.0 - jar + luckperms-placeholders-parent + 3.3-SNAPSHOT + + + luckperms-papi-expansion + luckperms-mvdw-hook + LuckPermsPlaceholders - PlaceholderAPI expansion for LuckPerms + Placeholders for LuckPerms https://github.com/lucko/LuckPermsPlaceholders @@ -26,39 +30,20 @@ https://github.com/lucko/LuckPermsPlaceholders + pom + UTF-8 + 1.8 + 1.8 - - clean package - Expansion-LuckPerms - - - org.apache.maven.plugins - maven-compiler-plugin - 3.5.1 - - 1.8 - 1.8 - - - - - me.lucko.luckperms luckperms-api - 3.0 - provided - - - - me.clip - placeholderapi - 2.6.0 + 3.3 provided @@ -75,10 +60,6 @@ luck-repo https://repo.lucko.me/ - - placeholderapi-repo - http://repo.extendedclip.com/content/repositories/placeholderapi/ - spigot-repo https://hub.spigotmc.org/nexus/content/repositories/snapshots/