feat: add some more placeholders and comments
This commit is contained in:
3 files changed
+147
-54
No files matched your search
@@ -3,6 +3,8 @@ package at.helpch.placeholderapi.expansion.server;
|
||||
import at.helpch.placeholderapi.expansion.server.util.ServerUtil;
|
||||
import com.google.common.cache.Cache;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
||||
import me.clip.placeholderapi.expansion.Cacheable;
|
||||
import me.clip.placeholderapi.expansion.Configurable;
|
||||
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
||||
@@ -12,19 +14,32 @@ import org.bukkit.World;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.ToIntFunction;
|
||||
import java.util.logging.Level;
|
||||
|
||||
public class ServerExpansion extends PlaceholderExpansion implements Cacheable, Configurable {
|
||||
public final class ServerExpansion extends PlaceholderExpansion implements Cacheable, Configurable {
|
||||
|
||||
private final Cache<String, Integer> cache = CacheBuilder.newBuilder()
|
||||
.expireAfterWrite(1, TimeUnit.MINUTES)
|
||||
.build();
|
||||
|
||||
private final Map<String, SimpleDateFormat> dateFormats = new HashMap<>();
|
||||
|
||||
private final Runtime runtime = Runtime.getRuntime();
|
||||
/**
|
||||
* Constant that represents how many bytes are in a megabyte
|
||||
*/
|
||||
private final int MB = 1_048_576;
|
||||
|
||||
// ----- Values from config
|
||||
private String serverName;
|
||||
|
||||
@Override
|
||||
public @NotNull String getIdentifier() {
|
||||
@@ -41,6 +56,12 @@ public class ServerExpansion extends PlaceholderExpansion implements Cacheable,
|
||||
return "3.0.0";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canRegister() {
|
||||
this.serverName = getString("server_name", "A Minecraft Server");
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
|
||||
@@ -48,36 +69,139 @@ public class ServerExpansion extends PlaceholderExpansion implements Cacheable,
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getDefaults() {
|
||||
return null;
|
||||
return ImmutableMap.<String, Object>builder()
|
||||
.put("server_name", "A Minecraft Server")
|
||||
.build();
|
||||
}
|
||||
|
||||
private int sumAllWorlds(@NotNull final ToIntFunction<? super World> function) {
|
||||
/**
|
||||
* Get some data from all worlds
|
||||
*
|
||||
* @param function data to get (e.g. total entities)
|
||||
* @return sum
|
||||
*/
|
||||
private int getFromAllWorlds(@NotNull final ToIntFunction<? super World> function) {
|
||||
return Bukkit.getWorlds()
|
||||
.stream()
|
||||
.mapToInt(function)
|
||||
.sum();
|
||||
}
|
||||
|
||||
private String getFromCache(@NotNull final String key, @NotNull final Callable<Integer> callable) {
|
||||
/**
|
||||
* Get a value from the {@link #cache}
|
||||
*
|
||||
* @param key key
|
||||
* @param callable cache method
|
||||
* @return value if found otherwise empty
|
||||
*/
|
||||
private @NotNull String getFromCache(@NotNull final String key, @NotNull final Callable<Integer> callable) {
|
||||
try {
|
||||
return String.valueOf(cache.get(key, callable));
|
||||
} catch (ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
PlaceholderAPIPlugin.getInstance()
|
||||
.getLogger()
|
||||
.log(Level.WARNING, "[server] Could not get '" + key + "' from cache", e);
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a boolean {@code boolean} as {@link PlaceholderAPIPlugin#booleanTrue()} or {@link PlaceholderAPIPlugin#booleanFalse()}
|
||||
*
|
||||
* @param bool boolean
|
||||
* @return {@link PlaceholderAPIPlugin#booleanTrue()} if the boolean is true, otherwise {@link PlaceholderAPIPlugin#booleanFalse()}
|
||||
*/
|
||||
private @NotNull String bool(final boolean bool) {
|
||||
return bool ? PlaceholderAPIPlugin.booleanTrue() : PlaceholderAPIPlugin.booleanFalse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of online players from a world
|
||||
*
|
||||
* @param worldName the name of the world
|
||||
* @return {@code -1} if {@code worldName} is empty or the world doesn't exist, otherwise {@link World#getPlayers()}.size()
|
||||
*/
|
||||
private int getOnlinePlayers(@NotNull final String worldName) {
|
||||
if (worldName.trim().isEmpty()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
final World world = Bukkit.getWorld(worldName);
|
||||
return world == null ? -1 : world.getPlayers().size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the current time with the given format
|
||||
*
|
||||
* @param format format
|
||||
* @return {@code null} if the format is empty or invalid, otherwise the current {@link Date} formatted
|
||||
*/
|
||||
private @Nullable String formatTime(@NotNull final String format) {
|
||||
if (format.trim().isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final SimpleDateFormat simpleDateFormat = dateFormats.computeIfAbsent(format, __ -> {
|
||||
try {
|
||||
return new SimpleDateFormat(format);
|
||||
} catch (IllegalArgumentException ignored) {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
return simpleDateFormat == null ? null : simpleDateFormat.format(new Date());
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String onRequest(OfflinePlayer player, @NotNull String params) {
|
||||
switch (params) {
|
||||
// ----- Players placeholders
|
||||
case "online":
|
||||
return String.valueOf(Bukkit.getOnlinePlayers().size());
|
||||
case "max_players":
|
||||
return String.valueOf(Bukkit.getMaxPlayers());
|
||||
case "unique_joins":
|
||||
return String.valueOf(Bukkit.getOfflinePlayers().length);
|
||||
// -----
|
||||
|
||||
// ----- Server software placeholders
|
||||
case "name":
|
||||
return this.serverName;
|
||||
case "variant":
|
||||
return ServerUtil.getVariant();
|
||||
case "version":
|
||||
return ServerUtil.getServerVersion();
|
||||
// TODO add version_build and version_full (same placeholder)
|
||||
// -----
|
||||
|
||||
// ----- RAM placeholders
|
||||
case "ram":
|
||||
return String.valueOf((runtime.totalMemory() - runtime.freeMemory()) / MB);
|
||||
case "ram_free":
|
||||
return String.valueOf(runtime.freeMemory() / MB);
|
||||
case "ram_total":
|
||||
return String.valueOf(runtime.totalMemory() / MB);
|
||||
case "ram_max":
|
||||
return String.valueOf(runtime.maxMemory() / MB);
|
||||
// -----
|
||||
|
||||
case "total_chunks":
|
||||
return getFromCache("chunks", () -> sumAllWorlds(world -> world.getLoadedChunks().length));
|
||||
return getFromCache("chunks", () -> getFromAllWorlds(world -> world.getLoadedChunks().length));
|
||||
case "total_living_entities":
|
||||
return getFromCache("livingEntities", () -> sumAllWorlds(world -> world.getLivingEntities().size()));
|
||||
return getFromCache("livingEntities", () -> getFromAllWorlds(world -> world.getLivingEntities().size()));
|
||||
case "total_entities":
|
||||
return getFromCache("totalEntities", () -> sumAllWorlds(world -> world.getEntities().size()));
|
||||
return getFromCache("totalEntities", () -> getFromAllWorlds(world -> world.getEntities().size()));
|
||||
case "has_whitelist":
|
||||
return bool(Bukkit.hasWhitelist());
|
||||
}
|
||||
|
||||
// online_<world name>
|
||||
if (params.startsWith("online_")) {
|
||||
return String.valueOf(getOnlinePlayers(params.replace("online_", "")));
|
||||
}
|
||||
|
||||
// time_<simple date format>
|
||||
if (params.startsWith("time_")) {
|
||||
return formatTime(params.replace("time_", ""));
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
@@ -13,6 +13,7 @@ public final class ServerUtil {
|
||||
|
||||
private static final Map<String, String> variants = new TreeMap<>();
|
||||
private static final String variant;
|
||||
private static final String serverVersion;
|
||||
|
||||
// TPS stuff
|
||||
private static final Object craftServer;
|
||||
@@ -28,6 +29,7 @@ public final class ServerUtil {
|
||||
variants.put("org.spigotmc.SpigotConfig", "Spigot");
|
||||
|
||||
variant = findVariant();
|
||||
serverVersion = Bukkit.getBukkitVersion().split("-")[0]; // The version is formatted as 1.20.1-R0.1-SNAPSHOT
|
||||
craftServer = getCraftServer();
|
||||
tpsField = getTpsHandler();
|
||||
}
|
||||
@@ -50,7 +52,7 @@ public final class ServerUtil {
|
||||
try {
|
||||
Class<?> clas;
|
||||
|
||||
if (VersionHelper.OVER_1_17) {
|
||||
if (VersionHelper.IS_1_17_OR_HIGHER) {
|
||||
clas = Class.forName("net.minecraft.server.MinecraftServer");
|
||||
} else {
|
||||
clas = Class.forName(String.format("net.minecraft.server.%s.MinecraftServer", VersionHelper.NMS_VERSION));
|
||||
@@ -70,17 +72,22 @@ public final class ServerUtil {
|
||||
try {
|
||||
Bukkit.class.getMethod("getTPS");
|
||||
hasTpsMethod = true;
|
||||
return null;
|
||||
} catch (NoSuchMethodException ignored) { }
|
||||
|
||||
if (craftServer == null) {
|
||||
PlaceholderAPIPlugin.getInstance().getLogger().log(Level.WARNING, "Could not get field 'recentTps' from class MinecraftServer because variable 'craftServer' is null");
|
||||
PlaceholderAPIPlugin.getInstance()
|
||||
.getLogger()
|
||||
.log(Level.WARNING, "[server] Could not get field 'recentTps' from class MinecraftServer because variable 'craftServer' is null");
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return craftServer.getClass().getField("recentTps");
|
||||
} catch (NoSuchFieldException e) {
|
||||
PlaceholderAPIPlugin.getInstance().getLogger().log(Level.WARNING, "Could not find field 'recentTps' in class " + craftServer.getClass().getName(), e);
|
||||
PlaceholderAPIPlugin.getInstance()
|
||||
.getLogger()
|
||||
.log(Level.WARNING, "[server] Could not find field 'recentTps' in class " + craftServer.getClass().getName(), e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -89,6 +96,10 @@ public final class ServerUtil {
|
||||
return variant;
|
||||
}
|
||||
|
||||
public static String getServerVersion() {
|
||||
return serverVersion;
|
||||
}
|
||||
|
||||
public static double[] getTps() {
|
||||
if (hasTpsMethod) {
|
||||
return Bukkit.getTPS();
|
||||
|
||||
@@ -38,55 +38,13 @@ public final class VersionHelper {
|
||||
|
||||
public static final String NMS_VERSION = getNmsVersion();
|
||||
|
||||
// Unbreakable change
|
||||
private static final int V1_11 = 1110;
|
||||
// Material and components on items change
|
||||
private static final int V1_13 = 1130;
|
||||
// PDC and customModelData
|
||||
private static final int V1_14 = 1140;
|
||||
// Paper adventure changes
|
||||
private static final int V1_16_5 = 1165;
|
||||
// SkullMeta#setOwningPlayer was added
|
||||
private static final int V1_12_1 = 1121;
|
||||
private static final int V1_17 = 1_17_0;
|
||||
|
||||
private static final int CURRENT_VERSION = getCurrentVersion();
|
||||
|
||||
private static final boolean IS_PAPER = checkPaper();
|
||||
|
||||
/**
|
||||
* Checks if the version supports Components or not
|
||||
* Spigot always false
|
||||
*/
|
||||
public static final boolean IS_COMPONENT_LEGACY = CURRENT_VERSION < V1_16_5;
|
||||
|
||||
/**
|
||||
* Checks if the version is lower than 1.13 due to the item changes
|
||||
*/
|
||||
public static final boolean IS_ITEM_LEGACY = CURRENT_VERSION < V1_13;
|
||||
|
||||
/**
|
||||
* Checks if the version supports the {@link org.bukkit.inventory.meta.ItemMeta#setUnbreakable(boolean)} method
|
||||
*/
|
||||
public static final boolean IS_UNBREAKABLE_LEGACY = CURRENT_VERSION < V1_11;
|
||||
|
||||
/**
|
||||
* Checks if the version supports {@link org.bukkit.persistence.PersistentDataContainer}
|
||||
*/
|
||||
public static final boolean IS_PDC_VERSION = CURRENT_VERSION >= V1_14;
|
||||
|
||||
/**
|
||||
* Checks if the version doesn't have {@link org.bukkit.inventory.meta.SkullMeta#setOwningPlayer(OfflinePlayer)} and
|
||||
* {@link org.bukkit.inventory.meta.SkullMeta#setOwner(String)} should be used instead
|
||||
*/
|
||||
public static final boolean IS_SKULL_OWNER_LEGACY = CURRENT_VERSION < V1_12_1;
|
||||
|
||||
/**
|
||||
* Checks if the version has {@link org.bukkit.inventory.meta.ItemMeta#setCustomModelData(Integer)}
|
||||
*/
|
||||
public static final boolean IS_CUSTOM_MODEL_DATA = CURRENT_VERSION >= V1_14;
|
||||
|
||||
public static final boolean OVER_1_17 = CURRENT_VERSION >= V1_17;
|
||||
public static final boolean IS_1_17_OR_HIGHER = CURRENT_VERSION >= V1_17;
|
||||
|
||||
/**
|
||||
* Check if the server has access to the Paper API
|
||||
|
||||
Reference in new issue
Block a user