Merge pull request #744 from Rsl1122/development

PR for 4.4.7
This commit is contained in:
Rsl1122 2018-10-07 11:46:27 +03:00 committed by GitHub
commit 1e19acb8ca
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 380 additions and 31 deletions

View File

@ -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.7",
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

View File

@ -81,7 +81,7 @@ public abstract class DBSystem implements SubSystem {
try {
Benchmark.start("Init Database");
initDatabase();
db.scheduleClean(1L);
db.scheduleClean(20L);
Log.info(locale.get().getString(PluginLang.ENABLED_DATABASE, db.getName()));
Benchmark.stop("Enable", "Init Database");
} catch (DBInitException e) {

View File

@ -16,7 +16,7 @@ public class GeoInfoLastUsedPatch extends Patch {
@Override
public void apply() {
addColumns(GeoInfoTable.TABLE_NAME,
addColumn(GeoInfoTable.TABLE_NAME,
GeoInfoTable.Col.LAST_USED + " bigint NOT NULL DEFAULT 0"
);
}

View File

@ -16,6 +16,6 @@ public class IPHashPatch extends Patch {
@Override
public void apply() {
addColumns(GeoInfoTable.Col.IP_HASH.get() + " varchar(200) DEFAULT ''");
addColumn(GeoInfoTable.TABLE_NAME, GeoInfoTable.Col.IP_HASH.get() + " varchar(200) DEFAULT ''");
}
}

View File

@ -40,7 +40,7 @@ public class KillsServerIDPatch extends Patch {
@Override
public void apply() {
addColumns(KillsTable.Col.SERVER_ID + " integer NOT NULL DEFAULT 0");
addColumn(KillsTable.TABLE_NAME, KillsTable.Col.SERVER_ID + " integer NOT NULL DEFAULT 0");
Map<Integer, Integer> sessionIDServerIDRelation = db.getSessionsTable().getIDServerIDRelation();

View File

@ -25,7 +25,7 @@ public class NicknameLastSeenPatch extends Patch {
@Override
public void apply() {
addColumns(NicknamesTable.TABLE_NAME,
addColumn(NicknamesTable.TABLE_NAME,
NicknamesTable.Col.LAST_USED + " bigint NOT NULL DEFAULT '0'"
);

View File

@ -78,11 +78,8 @@ public abstract class Patch {
});
}
protected void addColumns(String tableName, String... columnInfo) {
for (int i = 0; i < columnInfo.length; i++) {
columnInfo[i] = "ALTER TABLE " + tableName + " ADD " + (usingMySQL ? "" : "COLUMN ") + columnInfo[i];
}
db.executeUnsafe(columnInfo);
protected void addColumn(String tableName, String columnInfo) {
db.executeUnsafe("ALTER TABLE " + tableName + " ADD " + (usingMySQL ? "" : "COLUMN ") + columnInfo);
}
protected void dropTable(String name) {

View File

@ -16,7 +16,7 @@ public class SessionAFKTimePatch extends Patch {
@Override
public void apply() {
addColumns(SessionsTable.TABLE_NAME,
addColumn(SessionsTable.TABLE_NAME,
SessionsTable.Col.AFK_TIME + " bigint NOT NULL DEFAULT 0"
);
}

View File

@ -16,6 +16,6 @@ public class TransferPartitionPatch extends Patch {
@Override
public void apply() {
addColumns(TransferTable.TABLE_NAME, TransferTable.Col.PART + " bigint NOT NULL DEFAULT 0");
addColumn(TransferTable.TABLE_NAME, TransferTable.Col.PART + " bigint NOT NULL DEFAULT 0");
}
}

View File

@ -1,4 +1,9 @@
name: Plan
author: Rsl1122
main: com.djrapitops.plan.PlanBungee
version: 4.4.6
version: 4.4.7
softdepend:
- AdvancedBan
- LiteBans
- LuckPerms
- ViaVersion

View File

@ -1,7 +1,7 @@
name: Plan
author: Rsl1122
main: com.djrapitops.plan.Plan
version: 4.4.6
version: 4.4.7
softdepend:
- EssentialsX
- Towny
@ -20,6 +20,8 @@ softdepend:
- Kingdoms
- RedProtect
- AdvancedBan
- LuckPerms
- DiscordSRV
commands:
plan:
@ -88,7 +90,7 @@ permissions:
default: op
plan.webmanage:
description: Manage the webusers, delete, list, check
default: op;
default: op
plan.basic:
children:

View File

@ -85,6 +85,10 @@
<id>nucleus-repo</id>
<url>http://repo.drnaylor.co.uk/artifactory/list/minecraft</url>
</repository>
<repository>
<id>discordsrv-repo</id>
<url>https://ci.scarsz.me/plugin/repository/everything/</url>
</repository>
</repositories>
<dependencies>
@ -94,6 +98,12 @@
<version>4.3.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
<version>1.3</version>
</dependency>
<!-- Server APIs -->
<dependency>
@ -167,6 +177,18 @@
<version>1.6.0-PR1-S7.0</version>
<scope>provided</scope>
</dependency>
<dependency> <!-- Maven Central -->
<groupId>me.lucko.luckperms</groupId>
<artifactId>luckperms-api</artifactId>
<version>4.3</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>github.scarsz.discordsrv</groupId>
<artifactId>DiscordSRV</artifactId>
<version>1.16.4</version>
<scope>provided</scope>
</dependency>
<!-- Plugins requiring local install -->

View File

@ -10,6 +10,7 @@ import com.djrapitops.pluginbridge.plan.advancedban.AdvancedBanHook;
import com.djrapitops.pluginbridge.plan.askyblock.ASkyBlockHook;
import com.djrapitops.pluginbridge.plan.banmanager.BanManagerHook;
import com.djrapitops.pluginbridge.plan.buycraft.BuyCraftHook;
import com.djrapitops.pluginbridge.plan.discordsrv.DiscordSRVHook;
import com.djrapitops.pluginbridge.plan.essentials.EssentialsHook;
import com.djrapitops.pluginbridge.plan.factions.FactionsHook;
import com.djrapitops.pluginbridge.plan.griefprevention.GriefPreventionHook;
@ -18,6 +19,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 +77,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 +88,7 @@ public class Bridge {
new AdvancedBanHook(h),
new BuyCraftHook(h),
new LiteBansBungeeHook(h),
new LuckPermsHook(h),
new ViaVersionBungeeHook(h)
};
}
@ -97,6 +101,7 @@ public class Bridge {
new ASkyBlockHook(h),
new BanManagerHook(h),
new BuyCraftHook(h),
new DiscordSRVHook(h),
new EssentialsHook(h),
new FactionsHook(h),
new GriefPreventionHook(h),
@ -104,6 +109,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),

View File

@ -0,0 +1,124 @@
/*
* 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.discordsrv;
import com.djrapitops.plan.data.element.AnalysisContainer;
import com.djrapitops.plan.data.element.InspectContainer;
import com.djrapitops.plan.data.plugin.ContainerSize;
import com.djrapitops.plan.data.plugin.PluginData;
import com.djrapitops.plan.utilities.FormatUtils;
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 github.scarsz.discordsrv.DiscordSRV;
import github.scarsz.discordsrv.dependencies.jda.core.entities.Member;
import github.scarsz.discordsrv.dependencies.jda.core.entities.Role;
import github.scarsz.discordsrv.dependencies.jda.core.entities.User;
import github.scarsz.discordsrv.util.DiscordUtil;
import java.util.Collection;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
import org.apache.commons.text.TextStringBuilder;
/**
* PluginData for DiscordSRV plugin.
*
* @author Vankka
*/
public class DiscordSRVData extends PluginData {
public DiscordSRVData() {
super(ContainerSize.THIRD, "DiscordSRV");
setPluginIcon(Icon.called("discord").of(Family.BRAND).build());
}
@Override
public InspectContainer getPlayerData(UUID uuid, InspectContainer inspectContainer) {
if (!DiscordSRV.isReady) {
return inspectContainer;
}
String userId = DiscordSRV.getPlugin().getAccountLinkManager().getDiscordId(uuid);
User user = userId != null ? DiscordUtil.getUserById(userId) : null;
if (user == null) {
return inspectContainer;
}
inspectContainer.addValue(
getWithIcon("Username", Icon.called("user").of(Family.SOLID).of(Color.CYAN)),
"@" + user.getName() + "#" + user.getDiscriminator()
);
inspectContainer.addValue(
getWithIcon("Account creation date", Icon.called("plus").of(Family.SOLID).of(Color.BLUE)),
FormatUtils.formatTimeStampYear(user.getCreationTime().toEpochSecond() * 1000L)
);
Member member = DiscordSRV.getPlugin().getMainGuild().getMember(user);
if (member != null) {
addMemberData(member, inspectContainer);
}
return inspectContainer;
}
private void addMemberData(Member member, InspectContainer inspectContainer) {
String nickname = member.getNickname();
inspectContainer.addValue(
getWithIcon("Nickname", Icon.called("user-ninja").of(Family.SOLID).of(Color.ORANGE)),
nickname != null ? nickname : "None"
);
inspectContainer.addValue(
getWithIcon("Join Date", Icon.called("plus").of(Family.SOLID).of(Color.GREEN)),
FormatUtils.formatTimeStampYear(member.getJoinDate().toEpochSecond() * 1000L)
);
List<String> roles = member.getRoles().stream().map(Role::getName).collect(Collectors.toList()); // Ordered list of role names
if (!roles.isEmpty()) {
inspectContainer.addValue(
getWithIcon("Roles", Icon.called("user-circle").of(Family.SOLID).of(Color.RED)),
new TextStringBuilder().appendWithSeparators(roles, ", ").build()
);
}
}
@Override
public AnalysisContainer getServerData(Collection<UUID> uuids, AnalysisContainer analysisContainer) {
if (!DiscordSRV.isReady) {
return analysisContainer;
}
int accountsLinked = DiscordSRV.getPlugin().getAccountLinkManager().getLinkedAccounts().size();
int guildUsers = DiscordSRV.getPlugin().getMainGuild().getMembers().size();
analysisContainer.addValue(
getWithIcon("Accounts linked", Icon.called("link").of(Family.SOLID).of(Color.CYAN)),
accountsLinked
);
analysisContainer.addValue(
getWithIcon("Users in main guild", Icon.called("users").of(Family.SOLID).of(Color.GREEN)),
guildUsers
);
analysisContainer.addValue(
getWithIcon("Accounts linked / Total players", Icon.called("percentage").of(Family.SOLID).of(Color.TEAL)),
calculatePercentage(accountsLinked, uuids.size()) + "%"
);
analysisContainer.addValue(
getWithIcon("Accounts linked / Users in main guild", Icon.called("percentage").of(Family.SOLID).of(Color.LIGHT_GREEN)),
calculatePercentage(accountsLinked, guildUsers) + "%"
);
return analysisContainer;
}
private double calculatePercentage(int input1, int input2) {
if (input1 == 0 || input2 == 0)
return 0D;
return Math.round((double) input1 / input2 * 10000D) / 100D; // 2 decimals
}
}

View File

@ -0,0 +1,26 @@
/*
* 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.discordsrv;
import com.djrapitops.plan.data.plugin.HookHandler;
import com.djrapitops.pluginbridge.plan.Hook;
/**
* Hook for DiscordSRV plugin.
*
* @author Vankka
*/
public class DiscordSRVHook extends Hook {
public DiscordSRVHook(HookHandler hookHandler) {
super("github.scarsz.discordsrv.DiscordSRV", hookHandler);
}
@Override
public void hook() throws NoClassDefFoundError {
if (enabled) {
addPluginDataSource(new DiscordSRVData());
}
}
}

View File

@ -72,7 +72,8 @@ public class FactionsData extends PluginData {
if (!factions.isEmpty()) {
FactionsAccordion factionsAccordion = new FactionsAccordion(
factions,
analysisData.getValue(AnalysisKeys.PLAYERS_MUTATOR).orElse(new PlayersMutator(new ArrayList<>()))
Optional.ofNullable(analysisData).flatMap(c -> c.getValue(AnalysisKeys.PLAYERS_MUTATOR))
.orElse(new PlayersMutator(new ArrayList<>()))
);
analysisContainer.addHtml("factionAccordion", factionsAccordion.toHtml());

View File

@ -1,4 +1,4 @@
/*
/*
* 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
*/
@ -62,7 +62,8 @@ public class KingdomsData extends PluginData {
if (!kingdoms.isEmpty()) {
KingdomsAccordion kingdomsAccordion = new KingdomsAccordion(
kingdoms,
analysisData.getValue(AnalysisKeys.PLAYERS_MUTATOR).orElse(new PlayersMutator(new ArrayList<>()))
Optional.ofNullable(analysisData).flatMap(c -> c.getValue(AnalysisKeys.PLAYERS_MUTATOR))
.orElse(new PlayersMutator(new ArrayList<>()))
);
analysisContainer.addHtml("kingdomsAccordion", kingdomsAccordion.toHtml());

View File

@ -179,7 +179,8 @@ public class LiteBansData extends PluginData implements BanData {
if (objects.isEmpty()) {
table.addRow("No Data");
} else {
Map<UUID, String> playerNames = analysisData.getValue(AnalysisKeys.PLAYER_NAMES).orElse(new HashMap<>());
Map<UUID, String> playerNames = Optional.ofNullable(analysisData)
.flatMap(c -> c.getValue(AnalysisKeys.PLAYER_NAMES)).orElse(new HashMap<>());
for (LiteBansDBObj object : objects) {
UUID uuid = object.getUuid();
String name = playerNames.getOrDefault(uuid, uuid.toString());

View File

@ -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<String> 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<Track> 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<UUID> 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<Track> 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();
}
}

View File

@ -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()));
}
}
}

View File

@ -97,7 +97,8 @@ public class TownyData extends PluginData {
TownsAccordion townsAccordion = new TownsAccordion(
towns,
analysisData.getValue(AnalysisKeys.PLAYERS_MUTATOR).orElse(new PlayersMutator(new ArrayList<>()))
Optional.ofNullable(analysisData).flatMap(c -> c.getValue(AnalysisKeys.PLAYERS_MUTATOR))
.orElse(new PlayersMutator(new ArrayList<>()))
);
analysisContainer.addHtml("townAccordion", townsAccordion.toHtml());

View File

@ -9,7 +9,6 @@ import com.djrapitops.plan.data.element.InspectContainer;
import com.djrapitops.plan.data.plugin.ContainerSize;
import com.djrapitops.plan.data.plugin.PluginData;
import com.djrapitops.plan.data.store.keys.AnalysisKeys;
import com.djrapitops.plan.data.store.mutators.PlayersMutator;
import com.djrapitops.plan.system.cache.DataCache;
import com.djrapitops.plan.utilities.FormatUtils;
import com.djrapitops.plan.utilities.html.icon.Color;
@ -50,10 +49,11 @@ public class VaultEcoData extends PluginData {
@Override
public AnalysisContainer getServerData(Collection<UUID> collection, AnalysisContainer analysisContainer) {
List<FakeOfflinePlayer> offlinePlayers = analysisData.getValue(AnalysisKeys.PLAYERS_MUTATOR)
.map(PlayersMutator::all).orElse(new ArrayList<>())
.stream().map(FakeOfflinePlayer::new)
.collect(Collectors.toList());
List<FakeOfflinePlayer> offlinePlayers = Optional.ofNullable(analysisData)
.flatMap(c -> c.getValue(AnalysisKeys.PLAYERS_MUTATOR))
.map(mutator -> mutator.all().stream().map(FakeOfflinePlayer::new)
.collect(Collectors.toList()))
.orElse(new ArrayList<>());
Map<UUID, String> balances = new HashMap<>();
double totalBalance = 0.0;

View File

@ -9,7 +9,6 @@ import com.djrapitops.plan.data.element.InspectContainer;
import com.djrapitops.plan.data.plugin.ContainerSize;
import com.djrapitops.plan.data.plugin.PluginData;
import com.djrapitops.plan.data.store.keys.AnalysisKeys;
import com.djrapitops.plan.data.store.mutators.PlayersMutator;
import com.djrapitops.plan.system.cache.DataCache;
import com.djrapitops.pluginbridge.plan.FakeOfflinePlayer;
import net.milkbowl.vault.permission.Permission;
@ -49,10 +48,11 @@ public class VaultPermData extends PluginData {
@Override
public AnalysisContainer getServerData(Collection<UUID> collection, AnalysisContainer analysisContainer) {
List<FakeOfflinePlayer> offlinePlayers = analysisData.getValue(AnalysisKeys.PLAYERS_MUTATOR)
.map(PlayersMutator::all).orElse(new ArrayList<>())
.stream().map(FakeOfflinePlayer::new)
.collect(Collectors.toList());
List<FakeOfflinePlayer> offlinePlayers = Optional.ofNullable(analysisData)
.flatMap(c -> c.getValue(AnalysisKeys.PLAYERS_MUTATOR))
.map(mutator -> mutator.all().stream().map(FakeOfflinePlayer::new)
.collect(Collectors.toList()))
.orElse(new ArrayList<>());
Map<UUID, String> groups = new HashMap<>();
for (FakeOfflinePlayer p : offlinePlayers) {