diff --git a/Plan/src/main/java/com/djrapitops/plan/PlanSponge.java b/Plan/src/main/java/com/djrapitops/plan/PlanSponge.java index aa5dc60fd..e914ed0a8 100644 --- a/Plan/src/main/java/com/djrapitops/plan/PlanSponge.java +++ b/Plan/src/main/java/com/djrapitops/plan/PlanSponge.java @@ -20,12 +20,23 @@ import org.spongepowered.api.config.ConfigDir; import org.spongepowered.api.event.Listener; import org.spongepowered.api.event.game.state.GameStartedServerEvent; import org.spongepowered.api.event.game.state.GameStoppingServerEvent; +import org.spongepowered.api.plugin.Dependency; import org.spongepowered.api.plugin.Plugin; import java.io.File; import java.io.InputStream; -@Plugin(id = "plan", name = "Plan", version = "4.4.6", description = "Player Analytics Plugin by Rsl1122", authors = {"Rsl1122"}) +@Plugin( + id = "plan", + name = "Plan", + version = "4.4.6", + description = "Player Analytics Plugin by Rsl1122", + authors = {"Rsl1122"}, + dependencies = { + @Dependency(id = "nucleus", optional = true), + @Dependency(id = "luckperms", optional = true) + } +) public class PlanSponge extends SpongePlugin implements PlanPlugin { @Inject diff --git a/Plan/src/main/resources/bungee.yml b/Plan/src/main/resources/bungee.yml index 048b498cc..dd8f8c9ce 100644 --- a/Plan/src/main/resources/bungee.yml +++ b/Plan/src/main/resources/bungee.yml @@ -1,4 +1,9 @@ name: Plan author: Rsl1122 main: com.djrapitops.plan.PlanBungee -version: 4.4.6 \ No newline at end of file +version: 4.4.6 +softdepend: +- AdvancedBan +- LiteBans +- LuckPerms +- ViaVersion \ No newline at end of file diff --git a/Plan/src/main/resources/plugin.yml b/Plan/src/main/resources/plugin.yml index 56ef3675e..d66bbf18c 100644 --- a/Plan/src/main/resources/plugin.yml +++ b/Plan/src/main/resources/plugin.yml @@ -20,6 +20,7 @@ softdepend: - Kingdoms - RedProtect - AdvancedBan +- LuckPerms commands: plan: diff --git a/PlanPluginBridge/pom.xml b/PlanPluginBridge/pom.xml index a4f68f61d..d61b0fe23 100644 --- a/PlanPluginBridge/pom.xml +++ b/PlanPluginBridge/pom.xml @@ -94,6 +94,12 @@ 4.3.0-SNAPSHOT provided + + org.apache.commons + commons-text + 1.3 + + @@ -167,6 +173,12 @@ 1.6.0-PR1-S7.0 provided + + me.lucko.luckperms + luckperms-api + 4.3 + provided + diff --git a/PlanPluginBridge/src/main/java/com/djrapitops/pluginbridge/plan/Bridge.java b/PlanPluginBridge/src/main/java/com/djrapitops/pluginbridge/plan/Bridge.java index 2adf0dfbd..fc835bacd 100644 --- a/PlanPluginBridge/src/main/java/com/djrapitops/pluginbridge/plan/Bridge.java +++ b/PlanPluginBridge/src/main/java/com/djrapitops/pluginbridge/plan/Bridge.java @@ -18,6 +18,7 @@ import com.djrapitops.pluginbridge.plan.jobs.JobsHook; import com.djrapitops.pluginbridge.plan.kingdoms.KingdomsHook; import com.djrapitops.pluginbridge.plan.litebans.LiteBansBukkitHook; import com.djrapitops.pluginbridge.plan.litebans.LiteBansBungeeHook; +import com.djrapitops.pluginbridge.plan.luckperms.LuckPermsHook; import com.djrapitops.pluginbridge.plan.mcmmo.McmmoHook; import com.djrapitops.pluginbridge.plan.nucleus.NucleusHook; import com.djrapitops.pluginbridge.plan.protocolsupport.ProtocolSupportHook; @@ -75,6 +76,7 @@ public class Bridge { private static Hook[] getSpongeHooks(HookHandler h) { return new Hook[]{ new BuyCraftHook(h), + new LuckPermsHook(h), new SpongeEconomyHook(h), new NucleusHook(h) }; @@ -85,6 +87,7 @@ public class Bridge { new AdvancedBanHook(h), new BuyCraftHook(h), new LiteBansBungeeHook(h), + new LuckPermsHook(h), new ViaVersionBungeeHook(h) }; } @@ -104,6 +107,7 @@ public class Bridge { new JobsHook(h), new KingdomsHook(h), new LiteBansBukkitHook(h), + new LuckPermsHook(h), new McmmoHook(h), new SuperbVoteHook(h), new ProtocolSupportHook(h), diff --git a/PlanPluginBridge/src/main/java/com/djrapitops/pluginbridge/plan/luckperms/LuckPermsData.java b/PlanPluginBridge/src/main/java/com/djrapitops/pluginbridge/plan/luckperms/LuckPermsData.java new file mode 100644 index 000000000..9c10055ec --- /dev/null +++ b/PlanPluginBridge/src/main/java/com/djrapitops/pluginbridge/plan/luckperms/LuckPermsData.java @@ -0,0 +1,125 @@ +/* + * Licence is provided in the jar as license.yml also here: + * https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/license.yml + */ +package com.djrapitops.pluginbridge.plan.luckperms; + +import com.djrapitops.plan.data.element.AnalysisContainer; +import com.djrapitops.plan.data.element.InspectContainer; +import com.djrapitops.plan.data.element.TableContainer; +import com.djrapitops.plan.data.plugin.ContainerSize; +import com.djrapitops.plan.data.plugin.PluginData; +import com.djrapitops.plan.utilities.html.icon.Color; +import com.djrapitops.plan.utilities.html.icon.Family; +import com.djrapitops.plan.utilities.html.icon.Icon; +import java.util.*; +import java.util.stream.Collectors; +import me.lucko.luckperms.api.*; +import me.lucko.luckperms.api.caching.MetaData; +import org.apache.commons.text.TextStringBuilder; + +/** + * PluginData for LuckPerms plugin. + * + * @author Vankka + */ +public class LuckPermsData extends PluginData { + private LuckPermsApi api; + + public LuckPermsData(LuckPermsApi api) { + super(ContainerSize.THIRD, "LuckPerms"); + setPluginIcon(Icon.called("exclamation-triangle").of(Color.LIGHT_GREEN).build()); + + this.api = api; + } + + @Override + public InspectContainer getPlayerData(UUID uuid, InspectContainer inspectContainer) { + User user = api.getUser(uuid); + + if (user == null) { + inspectContainer.addValue("Data unavailable", "Could not get user data"); + return inspectContainer; + } + + MetaData metaData = user.getCachedData().getMetaData(Contexts.allowAll()); + String prefix = metaData.getPrefix(); + String suffix = metaData.getSuffix(); + + inspectContainer.addValue(getWithIcon("Primary group", Icon.called("user-friends").of(Family.SOLID)), user.getPrimaryGroup()); + inspectContainer.addValue(getWithIcon("Prefix", Icon.called("file-signature").of(Family.SOLID).of(Color.GREEN)), prefix != null ? prefix : "None"); + inspectContainer.addValue(getWithIcon("Suffix", Icon.called("file-signature").of(Family.SOLID).of(Color.BLUE)),suffix != null ? suffix : "None"); + + if (!metaData.getMeta().isEmpty()) { + TableContainer metaTable = new TableContainer( + getWithIcon("Meta", Icon.called("info-circle").of(Family.SOLID)), + getWithIcon("Value", Icon.called("file-alt").of(Family.SOLID)) + ); + metaData.getMeta().forEach((key, value) -> metaTable.addRow(key, value)); + inspectContainer.addTable("Meta", metaTable); + } + + List groups = user.getPermissions().stream() + .filter(Node::isGroupNode) + .map(Node::getGroupName) + .sorted() + .collect(Collectors.toList()); + + inspectContainer.addValue( + getWithIcon("Groups", Icon.called("user-friends").of(Family.SOLID)), + new TextStringBuilder().appendWithSeparators(groups, ", ").build() + ); + + Set tracks = api.getTracks(); + if (!tracks.isEmpty()) { + TableContainer trackTable = new TableContainer( + getWithIcon("Track", Icon.called("ellipsis-h").of(Family.SOLID)), + getWithIcon("Group", Icon.called("user-friends").of(Family.SOLID)) + ); + for (Track track : tracks) { + // reduce is used to get the last element + String currentGroup = api.getGroups().stream() + .map(this::getGroupDisplayName).filter(groups::contains) + .reduce((first, second) -> second).orElse("None"); + trackTable.addRow(track.getName(), currentGroup); + } + inspectContainer.addTable("Tracks", trackTable); + } + + return inspectContainer; + } + + @Override + public AnalysisContainer getServerData(Collection uuids, AnalysisContainer analysisContainer) { + // There will *always* be atleast 1 group + TableContainer groupTable = new TableContainer( + getWithIcon("Group", Icon.called("user-friends").of(Family.SOLID)), + getWithIcon("Weight", Icon.called("weight-hanging").of(Family.SOLID)), + getWithIcon("Permissions", Icon.called("list").of(Family.SOLID)) + ); + + api.getGroups().stream().sorted(Comparator.comparing(Group::getName)).forEach(group -> { + OptionalInt weight = group.getWeight(); + + groupTable.addRow(getGroupDisplayName(group), weight.isPresent() ? weight.getAsInt() : "None", group.getPermissions().size()); + }); + analysisContainer.addTable("Groups", groupTable); + + Set tracks = api.getTracks(); + if (!tracks.isEmpty()) { + TableContainer trackTable = new TableContainer( + getWithIcon("Track", Icon.called("ellipsis-h").of(Family.SOLID)), + getWithIcon("Size", Icon.called("list").of(Family.SOLID)) + ); + tracks.forEach(track -> trackTable.addRow(track.getName(), track.getSize())); + analysisContainer.addTable("Tracks", trackTable); + } + + return analysisContainer; + } + + private String getGroupDisplayName(Group group) { + String displayName = group.getDisplayName(); + return displayName != null ? displayName : group.getName(); + } +} diff --git a/PlanPluginBridge/src/main/java/com/djrapitops/pluginbridge/plan/luckperms/LuckPermsHook.java b/PlanPluginBridge/src/main/java/com/djrapitops/pluginbridge/plan/luckperms/LuckPermsHook.java new file mode 100644 index 000000000..341ed1853 --- /dev/null +++ b/PlanPluginBridge/src/main/java/com/djrapitops/pluginbridge/plan/luckperms/LuckPermsHook.java @@ -0,0 +1,27 @@ +/* + * Licence is provided in the jar as license.yml also here: + * https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/license.yml + */ +package com.djrapitops.pluginbridge.plan.luckperms; + +import com.djrapitops.plan.data.plugin.HookHandler; +import com.djrapitops.pluginbridge.plan.Hook; +import me.lucko.luckperms.LuckPerms; + +/** + * Hook for LuckPerms plugin. + * + * @author Vankka + */ +public class LuckPermsHook extends Hook { + public LuckPermsHook(HookHandler hookHandler) { + super("me.lucko.luckperms.LuckPerms", hookHandler); + } + + @Override + public void hook() throws IllegalStateException { + if (enabled) { + addPluginDataSource(new LuckPermsData(LuckPerms.getApi())); + } + } +}