207 lines
7.5 KiB
Java
207 lines
7.5 KiB
Java
package com.artemis.the.gr8.playerstats.utils;
|
|
|
|
import com.artemis.the.gr8.playerstats.config.ConfigHandler;
|
|
import com.artemis.the.gr8.playerstats.multithreading.ThreadManager;
|
|
import org.bukkit.Bukkit;
|
|
import org.bukkit.OfflinePlayer;
|
|
import org.jetbrains.annotations.Contract;
|
|
import org.jetbrains.annotations.NotNull;
|
|
|
|
import java.util.*;
|
|
import java.util.concurrent.ConcurrentHashMap;
|
|
import java.util.concurrent.Executors;
|
|
import java.util.concurrent.ForkJoinPool;
|
|
import java.util.function.Predicate;
|
|
|
|
/**
|
|
* A utility class that deals with OfflinePlayers. It stores a list
|
|
* of all OfflinePlayer-names that need to be included in statistic
|
|
* calculations, and can retrieve the corresponding OfflinePlayer
|
|
* object for a given player-name.
|
|
*/
|
|
public final class OfflinePlayerHandler extends FileHandler {
|
|
|
|
private static volatile OfflinePlayerHandler instance;
|
|
private final ConfigHandler config;
|
|
private static ConcurrentHashMap<String, UUID> includedPlayerUUIDs;
|
|
private static ConcurrentHashMap<String, UUID> excludedPlayerUUIDs;
|
|
|
|
private OfflinePlayerHandler() {
|
|
super("excluded_players.yml");
|
|
config = ConfigHandler.getInstance();
|
|
|
|
loadOfflinePlayers();
|
|
}
|
|
|
|
public static OfflinePlayerHandler getInstance() {
|
|
OfflinePlayerHandler localVar = instance;
|
|
if (localVar != null) {
|
|
return localVar;
|
|
}
|
|
|
|
synchronized (OfflinePlayerHandler.class) {
|
|
if (instance == null) {
|
|
instance = new OfflinePlayerHandler();
|
|
}
|
|
return instance;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void reload() {
|
|
super.reload();
|
|
loadOfflinePlayers();
|
|
}
|
|
|
|
/**
|
|
* Checks if a given player is currently
|
|
* included for /statistic lookups.
|
|
*
|
|
* @param playerName String (case-sensitive)
|
|
* @return true if this player is included
|
|
*/
|
|
public boolean isLoadedPlayer(String playerName) {
|
|
return includedPlayerUUIDs.containsKey(playerName);
|
|
}
|
|
|
|
public boolean isExcludedPlayer(String playerName) {
|
|
return excludedPlayerUUIDs.containsKey(playerName);
|
|
}
|
|
|
|
public boolean isExcludedPlayer(UUID uniqueID) {
|
|
return excludedPlayerUUIDs.containsValue(uniqueID);
|
|
}
|
|
|
|
public void addLoadedPlayerToExcludeList(String playerName) throws IllegalArgumentException {
|
|
UUID uuid = includedPlayerUUIDs.get(playerName);
|
|
if (uuid == null) {
|
|
throw new IllegalArgumentException("This player is not loaded, and therefore cannot be excluded!");
|
|
}
|
|
super.writeEntryToList("excluded", uuid.toString());
|
|
includedPlayerUUIDs.remove(playerName);
|
|
excludedPlayerUUIDs.put(playerName, uuid);
|
|
}
|
|
|
|
public void addExcludedPlayerToLoadedList(String playerName) {
|
|
UUID uuid = excludedPlayerUUIDs.get(playerName);
|
|
if (uuid == null) {
|
|
throw new IllegalArgumentException("This player is not excluded, and therefore cannot be un-excluded!");
|
|
}
|
|
super.removeEntryFromList("excluded", uuid.toString());
|
|
excludedPlayerUUIDs.remove(playerName);
|
|
includedPlayerUUIDs.put(playerName, uuid);
|
|
}
|
|
|
|
@Contract(" -> new")
|
|
public @NotNull ArrayList<String> getExcludedPlayerNames() {
|
|
return Collections.list(excludedPlayerUUIDs.keys());
|
|
}
|
|
|
|
/**
|
|
* Gets an ArrayList of names from all OfflinePlayers that should
|
|
* be included in statistic calculations.
|
|
*
|
|
* @return the ArrayList
|
|
*/
|
|
@Contract(" -> new")
|
|
public @NotNull ArrayList<String> getLoadedOfflinePlayerNames() {
|
|
return Collections.list(includedPlayerUUIDs.keys());
|
|
}
|
|
|
|
/**
|
|
* Gets the number of OfflinePlayers that are
|
|
* currently included in statistic calculations.
|
|
*
|
|
* @return the number of included OfflinePlayers
|
|
*/
|
|
public int getOfflinePlayerCount() {
|
|
return includedPlayerUUIDs.size();
|
|
}
|
|
|
|
/**
|
|
* Uses the playerName to get the player's UUID from a private HashMap,
|
|
* and uses the UUID to get the corresponding OfflinePlayer Object.
|
|
*
|
|
* @param playerName name of the target player (case-sensitive)
|
|
* @return OfflinePlayer
|
|
* @throws IllegalArgumentException if this player is not on the list
|
|
* of players that should be included in statistic calculations
|
|
*/
|
|
public @NotNull OfflinePlayer getOfflinePlayer(String playerName) throws IllegalArgumentException {
|
|
if (includedPlayerUUIDs.get(playerName) != null) {
|
|
return Bukkit.getOfflinePlayer(includedPlayerUUIDs.get(playerName));
|
|
}
|
|
else {
|
|
MyLogger.logWarning("Cannot calculate statistics for player-name: " + playerName +
|
|
"! Double-check if the name is spelled correctly (including capital letters), " +
|
|
"or if any of your config settings exclude them");
|
|
throw new IllegalArgumentException("Cannot convert this player-name into a valid Player to calculate statistics for");
|
|
}
|
|
}
|
|
|
|
private void loadOfflinePlayers() {
|
|
Executors.newSingleThreadExecutor().execute(() -> {
|
|
loadExcludedPlayerNames();
|
|
loadIncludedOfflinePlayers();
|
|
});
|
|
}
|
|
|
|
private void loadIncludedOfflinePlayers() {
|
|
long time = System.currentTimeMillis();
|
|
|
|
OfflinePlayer[] offlinePlayers;
|
|
if (config.whitelistOnly()) {
|
|
offlinePlayers = getWhitelistedPlayers();
|
|
} else if (config.excludeBanned()) {
|
|
offlinePlayers = getNonBannedPlayers();
|
|
} else {
|
|
offlinePlayers = Bukkit.getOfflinePlayers();
|
|
}
|
|
|
|
int size = includedPlayerUUIDs != null ? includedPlayerUUIDs.size() : 16;
|
|
includedPlayerUUIDs = new ConcurrentHashMap<>(size);
|
|
|
|
ForkJoinPool.commonPool().invoke(ThreadManager.getPlayerLoadAction(offlinePlayers, includedPlayerUUIDs));
|
|
|
|
MyLogger.actionFinished();
|
|
MyLogger.logLowLevelTask(("Loaded " + includedPlayerUUIDs.size() + " offline players"), time);
|
|
}
|
|
|
|
private void loadExcludedPlayerNames() {
|
|
long time = System.currentTimeMillis();
|
|
|
|
excludedPlayerUUIDs = new ConcurrentHashMap<>();
|
|
List<String> excluded = super.getFileConfiguration().getStringList("excluded");
|
|
excluded.stream()
|
|
.filter(Objects::nonNull)
|
|
.map(UUID::fromString)
|
|
.forEach(uuid -> {
|
|
OfflinePlayer player = Bukkit.getOfflinePlayer(uuid);
|
|
String playerName = player.getName();
|
|
if (playerName != null) {
|
|
excludedPlayerUUIDs.put(playerName, uuid);
|
|
}
|
|
});
|
|
|
|
MyLogger.logLowLevelTask("Loaded " + excludedPlayerUUIDs.size() + " excluded players from file", time);
|
|
}
|
|
|
|
private OfflinePlayer[] getWhitelistedPlayers() {
|
|
return Bukkit.getWhitelistedPlayers().toArray(OfflinePlayer[]::new);
|
|
}
|
|
|
|
private @NotNull OfflinePlayer[] getNonBannedPlayers() {
|
|
if (Bukkit.getPluginManager().isPluginEnabled("LiteBans")) {
|
|
return Arrays.stream(Bukkit.getOfflinePlayers())
|
|
.parallel()
|
|
.filter(Predicate.not(OfflinePlayer::isBanned))
|
|
.toArray(OfflinePlayer[]::new);
|
|
}
|
|
|
|
Set<OfflinePlayer> banList = Bukkit.getBannedPlayers();
|
|
return Arrays.stream(Bukkit.getOfflinePlayers())
|
|
.parallel()
|
|
.filter(Predicate.not(banList::contains))
|
|
.toArray(OfflinePlayer[]::new);
|
|
}
|
|
} |