mirror of
https://github.com/CodedRed-Spigot/PlayTimes.git
synced 2026-11-06 01:32:33 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5dc8a9c1a9 | ||
|
|
79c36751ca | ||
|
|
7644a91756 | ||
|
|
7abae06f54 | ||
|
|
f58f182bc4 | ||
|
|
7e7a16bcdf | ||
|
|
963ef56818 | ||
|
|
9075dcd4ad | ||
|
|
8300a4d2e3 | ||
|
|
ab7178c3bb | ||
|
|
52d11b9958 | ||
|
|
dad538a890 | ||
|
|
30b43df049 | ||
|
|
6e0043e197 | ||
|
|
97cba3598a | ||
|
|
32110fc2f2 | ||
|
|
8e5db3928f | ||
|
|
1e7a5ffadb | ||
|
|
62a5966270 | ||
|
|
47666f3a74 | ||
|
|
4ae41d91cb | ||
|
|
ea39b43725 | ||
|
|
7ab49c419d | ||
|
|
ecea1640ab | ||
|
|
cbc8253b4b | ||
|
|
e292e6e1b3 | ||
|
|
fc8e2dc3c6 | ||
|
|
1cbfe86785 | ||
|
|
b4b899b031 | ||
|
|
3f2fe03fff | ||
|
|
71917d811d | ||
|
|
185510320b | ||
|
|
bf320aca14 | ||
|
|
4497848cc5 | ||
|
|
8ff6cd3a33 | ||
|
|
ab497b8157 | ||
|
|
a13fdba083 | ||
|
|
044c4c8f13 | ||
|
|
2d6501dbfc | ||
|
|
3435ac4fdd |
No files matched your search
@@ -0,0 +1,22 @@
|
||||
name: Build Minecraft Plugin
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: '17'
|
||||
distribution: 'adopt'
|
||||
|
||||
- name: Grant execute permission for gradlew
|
||||
run: chmod +x ./gradlew
|
||||
|
||||
- name: Build with Gradle
|
||||
run: ./gradlew build
|
||||
+33
@@ -10,6 +10,8 @@ out/
|
||||
# mpeltonen/sbt-idea plugin
|
||||
.idea_modules/
|
||||
|
||||
bin
|
||||
|
||||
# JIRA plugin
|
||||
atlassian-ide-plugin.xml
|
||||
|
||||
@@ -116,3 +118,34 @@ run/
|
||||
|
||||
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
|
||||
!gradle-wrapper.jar
|
||||
|
||||
|
||||
# VS Code directories
|
||||
.vscode/
|
||||
|
||||
# User workspace settings
|
||||
.vscode/settings.json
|
||||
|
||||
# User workspace launch configurations
|
||||
.vscode/launch.json
|
||||
|
||||
# User workspace tasks
|
||||
.vscode/tasks.json
|
||||
|
||||
# Recommended extensions for this workspace
|
||||
.vscode/extensions.json
|
||||
|
||||
# VS Code directories for Java development
|
||||
.vscode-test/
|
||||
|
||||
# VS Code for Java standalone server
|
||||
.vscode-server/
|
||||
|
||||
# Windows image file caches
|
||||
iconcache_*.db
|
||||
|
||||
# Windows Installer directory
|
||||
Installer/
|
||||
|
||||
# ASP.NET Scaffolding
|
||||
ScaffoldingReadMe.txt
|
||||
@@ -22,7 +22,13 @@
|
||||
|
||||
## About The Project
|
||||
|
||||
PlayTimes is your ideal plugin for gamified competition! It enables players to compete for the most time played, with leaderboards for showing off achievements. Beyond player time, you can also monitor server uptime. Future plans include introducing PlayTime Rewards, Ranks, and Shop! Start using PlayTimes today to add an exciting dimension to your server.
|
||||
Introducing PlayTimes, the ultimate plugin for your server! Elevate the gaming experience by allowing players to showcase their skills and compete for top positions on the prestigious playtime leaderboards. Not only can you effortlessly monitor the playtime of online and offline players, but you can also keep track of the server's uptime for maximum efficiency. But that's not all! Brace yourself for an array of exciting features that are on the horizon, including PlayTime Rewards, PlayTime Ranks, and the immersive PlayTime Shop. Get ready to take your server to the next level with PlayTimes!
|
||||
|
||||
<img src="https://imgur.com/KebViUJ.gif"> <img src="https://imgur.com/v6ErIo9.gif">
|
||||
|
||||
<img src="https://imgur.com/VGZ0iuV.gif"> <img src="https://imgur.com/f4A5LRY.gif">
|
||||
|
||||
<img src="https://imgur.com/kOy8YSx.gif"> <img src="https://imgur.com/gNYsU00.gif">
|
||||
|
||||
## Usage
|
||||
|
||||
|
||||
+4
-3
@@ -1,11 +1,10 @@
|
||||
plugins {
|
||||
id 'java'
|
||||
id 'dev.codedred.craftengine' version '1.0.0'
|
||||
}
|
||||
|
||||
|
||||
group = 'dev.codedred'
|
||||
version = '1.5'
|
||||
version = '1.5.4'
|
||||
|
||||
|
||||
repositories {
|
||||
@@ -27,9 +26,11 @@ repositories {
|
||||
|
||||
dependencies {
|
||||
implementation 'org.jetbrains:annotations:23.0.0'
|
||||
compileOnly 'org.spigotmc:spigot-api:1.19.3-R0.1-SNAPSHOT'
|
||||
compileOnly 'org.spigotmc:spigot-api:1.20.1-R0.1-SNAPSHOT'
|
||||
compileOnly 'me.clip:placeholderapi:2.10.9'
|
||||
|
||||
compileOnly 'org.projectlombok:lombok:1.18.28'
|
||||
annotationProcessor 'org.projectlombok:lombok:1.18.28'
|
||||
}
|
||||
|
||||
def targetJavaVersion = 17
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package me.codedred.playtimes;
|
||||
|
||||
import java.util.*;
|
||||
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
||||
import me.codedred.playtimes.data.DataManager;
|
||||
import me.codedred.playtimes.data.database.manager.DatabaseManager;
|
||||
import me.codedred.playtimes.models.Leaderboard;
|
||||
import me.codedred.playtimes.statistics.StatManager;
|
||||
import me.codedred.playtimes.statistics.StatisticType;
|
||||
@@ -10,122 +13,169 @@ import org.bukkit.ChatColor;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class Expansions extends PlaceholderExpansion {
|
||||
|
||||
@Override
|
||||
public boolean canRegister() {
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public boolean canRegister() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getAuthor() {
|
||||
return "CodedRed";
|
||||
}
|
||||
@Override
|
||||
public @NotNull String getAuthor() {
|
||||
return "CodedRed";
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getIdentifier() {
|
||||
return "PlayTimes";
|
||||
}
|
||||
@Override
|
||||
public @NotNull String getIdentifier() {
|
||||
return "PlayTimes";
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getVersion() {
|
||||
return "1.5";
|
||||
}
|
||||
@Override
|
||||
public @NotNull String getVersion() {
|
||||
return "1.5.4";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean persist() {
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public boolean persist() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onRequest(OfflinePlayer player, @NotNull String identifier) {
|
||||
identifier = identifier.toLowerCase();
|
||||
switch (identifier) {
|
||||
case "playtime":
|
||||
return getPlayerPlayTime(player);
|
||||
case "uptime":
|
||||
return StatManager.getInstance().getUptime();
|
||||
case "joindate":
|
||||
return StatManager.getInstance().getJoinDate(player.getUniqueId());
|
||||
default:
|
||||
return handleLeaderboardIdentifier(identifier);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public String onRequest(OfflinePlayer player, @NotNull String identifier) {
|
||||
identifier = identifier.toLowerCase();
|
||||
switch (identifier) {
|
||||
case "playtime":
|
||||
return getPlayerPlayTime(player);
|
||||
case "uptime":
|
||||
return StatManager.getInstance().getUptime();
|
||||
case "joindate":
|
||||
return StatManager.getInstance().getJoinDate(player.getUniqueId());
|
||||
case "timesjoined":
|
||||
return Long.toString(
|
||||
StatManager
|
||||
.getInstance()
|
||||
.getPlayerStat(player.getUniqueId(), StatisticType.TIMES_JOINED)
|
||||
);
|
||||
// New cases for %PlayTimes_db_serverId% and %PlayTimes_total%
|
||||
case "total":
|
||||
return getTotalPlaytime(player);
|
||||
default:
|
||||
if (identifier.startsWith("db_")) {
|
||||
return getServerSpecificPlaytime(player, identifier.substring(3));
|
||||
}
|
||||
return handleLeaderboardIdentifier(identifier);
|
||||
}
|
||||
}
|
||||
|
||||
private String getPlayerPlayTime(OfflinePlayer player) {
|
||||
StatManager stats = StatManager.getInstance();
|
||||
TimeManager timeManager = TimeManager.getInstance();
|
||||
return timeManager.buildFormat(stats.getPlayerStat(player.getUniqueId(), StatisticType.PLAYTIME) / 20);
|
||||
}
|
||||
private String getTotalPlaytime(OfflinePlayer player) {
|
||||
if (
|
||||
DataManager
|
||||
.getInstance()
|
||||
.getDBConfig()
|
||||
.getBoolean("database-settings.enabled")
|
||||
) {
|
||||
TimeManager timeManager = TimeManager.getInstance();
|
||||
Long totalPlaytime = DatabaseManager
|
||||
.getInstance()
|
||||
.getTotalPlayTime(player.getUniqueId());
|
||||
return timeManager.buildFormat(totalPlaytime != null ? totalPlaytime : 0);
|
||||
}
|
||||
return "N/A";
|
||||
}
|
||||
|
||||
private String handleLeaderboardIdentifier(String identifier) {
|
||||
if (identifier.contains("topname")) {
|
||||
return getLeaderboardPlayerName(identifier);
|
||||
} else if (identifier.contains("toptime")) {
|
||||
return getLeaderboardPlayTime(identifier);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
private String getServerSpecificPlaytime(
|
||||
OfflinePlayer player,
|
||||
String serverId
|
||||
) {
|
||||
if (
|
||||
DataManager
|
||||
.getInstance()
|
||||
.getDBConfig()
|
||||
.getBoolean("database-settings.enabled")
|
||||
) {
|
||||
TimeManager timeManager = TimeManager.getInstance();
|
||||
Long playtime = DatabaseManager
|
||||
.getInstance()
|
||||
.getPlayTimeForServer(player.getUniqueId(), serverId);
|
||||
return timeManager.buildFormat(playtime != null ? playtime : 0);
|
||||
}
|
||||
return "N/A";
|
||||
}
|
||||
|
||||
private String getLeaderboardPlayerName(String identifier) {
|
||||
Leaderboard board = new Leaderboard();
|
||||
int val = parseLeaderboardPosition(identifier);
|
||||
if (val == -1) {
|
||||
return ChatColor.RED + "Invalid leaderboard position!";
|
||||
}
|
||||
private String getPlayerPlayTime(OfflinePlayer player) {
|
||||
StatManager stats = StatManager.getInstance();
|
||||
TimeManager timeManager = TimeManager.getInstance();
|
||||
return timeManager.buildFormat(
|
||||
stats.getPlayerStat(player.getUniqueId(), StatisticType.PLAYTIME) / 20
|
||||
);
|
||||
}
|
||||
|
||||
List<UUID> players = getTopPlayersUUID(board);
|
||||
if (players.size() < val + 1)
|
||||
return "N/A";
|
||||
private String handleLeaderboardIdentifier(String identifier) {
|
||||
if (identifier.contains("topname")) {
|
||||
return getLeaderboardPlayerName(identifier);
|
||||
} else if (identifier.contains("toptime")) {
|
||||
return getLeaderboardPlayTime(identifier);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
OfflinePlayer targetPlayer = Bukkit.getOfflinePlayer(players.get(val));
|
||||
return targetPlayer.getName();
|
||||
}
|
||||
private String getLeaderboardPlayerName(String identifier) {
|
||||
Leaderboard board = new Leaderboard();
|
||||
int val = parseLeaderboardPosition(identifier);
|
||||
if (val == -1) {
|
||||
return ChatColor.RED + "Invalid leaderboard position!";
|
||||
}
|
||||
|
||||
private String getLeaderboardPlayTime(String identifier) {
|
||||
Leaderboard board = new Leaderboard();
|
||||
int val = parseLeaderboardPosition(identifier);
|
||||
if (val == -1) {
|
||||
return ChatColor.RED + "Invalid leaderboard position!";
|
||||
}
|
||||
List<UUID> players = getTopPlayersUUID(board);
|
||||
if (players.size() < val + 1) return "N/A";
|
||||
|
||||
List<Integer> players = getTopPlayersPlayTime(board);
|
||||
if (players.size() < val + 1)
|
||||
return "N/A";
|
||||
OfflinePlayer targetPlayer = Bukkit.getOfflinePlayer(players.get(val));
|
||||
return targetPlayer.getName();
|
||||
}
|
||||
|
||||
return TimeManager.getInstance().buildFormat(players.get(val) / 20);
|
||||
}
|
||||
private String getLeaderboardPlayTime(String identifier) {
|
||||
Leaderboard board = new Leaderboard();
|
||||
int val = parseLeaderboardPosition(identifier);
|
||||
if (val == -1) {
|
||||
return ChatColor.RED + "Invalid leaderboard position!";
|
||||
}
|
||||
|
||||
private List<UUID> getTopPlayersUUID(Leaderboard board) {
|
||||
List<UUID> players = new ArrayList<>();
|
||||
for (Map.Entry<String, Integer> entry : board.getTopTen().entrySet())
|
||||
players.add(UUID.fromString(entry.getKey()));
|
||||
return players;
|
||||
}
|
||||
List<Integer> players = getTopPlayersPlayTime(board);
|
||||
if (players.size() < val + 1) return "N/A";
|
||||
|
||||
private List<Integer> getTopPlayersPlayTime(Leaderboard board) {
|
||||
List<Integer> players = new ArrayList<>();
|
||||
for (Map.Entry<String, Integer> entry : board.getTopTen().entrySet())
|
||||
players.add(entry.getValue());
|
||||
return players;
|
||||
}
|
||||
return TimeManager.getInstance().buildFormat(players.get(val) / 20);
|
||||
}
|
||||
|
||||
private int parseLeaderboardPosition(String identifier) {
|
||||
String num = identifier.substring(7);
|
||||
if (isInteger(num)) {
|
||||
return (Integer.parseInt(num) < 1) ? 0 : Integer.parseInt(num) - 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
private List<UUID> getTopPlayersUUID(Leaderboard board) {
|
||||
List<UUID> players = new ArrayList<>();
|
||||
for (Map.Entry<String, Integer> entry : board
|
||||
.getTopTen()
|
||||
.entrySet()) players.add(UUID.fromString(entry.getKey()));
|
||||
return players;
|
||||
}
|
||||
|
||||
private boolean isInteger(String str) {
|
||||
try {
|
||||
Integer.parseInt(str);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
private List<Integer> getTopPlayersPlayTime(Leaderboard board) {
|
||||
List<Integer> players = new ArrayList<>();
|
||||
for (Map.Entry<String, Integer> entry : board
|
||||
.getTopTen()
|
||||
.entrySet()) players.add(entry.getValue());
|
||||
return players;
|
||||
}
|
||||
|
||||
private int parseLeaderboardPosition(String identifier) {
|
||||
String num = identifier.substring(7);
|
||||
if (isInteger(num)) {
|
||||
return (Integer.parseInt(num) < 1) ? 0 : Integer.parseInt(num) - 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private boolean isInteger(String str) {
|
||||
try {
|
||||
Integer.parseInt(str);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,9 +1,14 @@
|
||||
package me.codedred.playtimes;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Objects;
|
||||
import me.codedred.playtimes.commands.Time;
|
||||
import me.codedred.playtimes.commands.TopTime;
|
||||
import me.codedred.playtimes.commands.Uptime;
|
||||
import me.codedred.playtimes.commands.completer.TimeTabCompleter;
|
||||
import me.codedred.playtimes.data.DataManager;
|
||||
import me.codedred.playtimes.data.database.manager.DatabaseManager;
|
||||
import me.codedred.playtimes.listeners.Join;
|
||||
import me.codedred.playtimes.listeners.Quit;
|
||||
import me.codedred.playtimes.server.ServerManager;
|
||||
@@ -14,72 +19,122 @@ import org.bukkit.Bukkit;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
|
||||
public class PlayTimes extends JavaPlugin {
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
checkForUpdate();
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
checkForUpdate();
|
||||
DataManager dataManager = DataManager.getInstance();
|
||||
dataManager.reloadAll();
|
||||
|
||||
ServerManager.getInstance().register();
|
||||
StatManager.getInstance().registerStatistics();
|
||||
TimeManager.getInstance().registerTimings();
|
||||
|
||||
if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null) {
|
||||
Expansions exp = new Expansions();
|
||||
exp.register();
|
||||
getLogger().info("[PlayTimes] PlaceholdersAPI Hooked!");
|
||||
}
|
||||
ServerManager.getInstance().register();
|
||||
StatManager.getInstance().registerStatistics();
|
||||
TimeManager.getInstance().registerTimings();
|
||||
|
||||
registerEvents();
|
||||
registerCommands();
|
||||
loadDatabase();
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
Metrics metrics = new Metrics(this, 5289);
|
||||
getLogger().info("[PlayTimes] Successfully loaded.");
|
||||
}
|
||||
if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null) {
|
||||
Expansions exp = new Expansions();
|
||||
exp.register();
|
||||
getLogger().info("PlaceholdersAPI Hooked!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
getLogger().info("PlayTimes shutting down");
|
||||
}
|
||||
registerEvents();
|
||||
registerCommands();
|
||||
|
||||
private void registerEvents() {
|
||||
PluginManager pm = getServer().getPluginManager();
|
||||
pm.registerEvents(new Join(), this);
|
||||
pm.registerEvents(new Quit(), this);
|
||||
}
|
||||
@SuppressWarnings("unused")
|
||||
Metrics metrics = new Metrics(this, 5289);
|
||||
getLogger().info("Successfully loaded.");
|
||||
}
|
||||
|
||||
private void registerCommands() {
|
||||
Objects.requireNonNull(getCommand("playtime")).setExecutor(
|
||||
new Time());
|
||||
Objects.requireNonNull(getCommand("uptime")).setExecutor(
|
||||
new Uptime());
|
||||
Objects.requireNonNull(getCommand("topplaytime")).setExecutor(
|
||||
new TopTime());
|
||||
Objects.requireNonNull(this.getCommand("pt")).setTabCompleter(new TimeTabCompleter());
|
||||
@Override
|
||||
public void onDisable() {
|
||||
getLogger().info("PlayTimes shutting down");
|
||||
}
|
||||
|
||||
}
|
||||
private void registerEvents() {
|
||||
PluginManager pm = getServer().getPluginManager();
|
||||
pm.registerEvents(new Join(), this);
|
||||
pm.registerEvents(new Quit(), this);
|
||||
}
|
||||
|
||||
private void checkForUpdate() {
|
||||
Bukkit.getScheduler().runTaskAsynchronously(this, () -> {
|
||||
UpdateChecker updater = new UpdateChecker(this, 58858);
|
||||
try {
|
||||
if (!updater.checkForUpdates()) {
|
||||
getLogger().warning(ChatUtil.format("&eYou are using an older version of PlayTimes!"));
|
||||
getLogger().info(ChatUtil.format("&eDownload the newest version here:"));
|
||||
getLogger().info(ChatUtil.format("&bhttps://www.spigotmc.org/resources/58858/"));
|
||||
} else {
|
||||
getLogger().info("[PlayTimes] Plugin is up to date! - " + getDescription().getVersion());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
getLogger().warning("[PlayTimes] Could not check for updates!");
|
||||
}
|
||||
});
|
||||
}
|
||||
private void registerCommands() {
|
||||
Objects.requireNonNull(getCommand("playtime")).setExecutor(new Time());
|
||||
Objects.requireNonNull(getCommand("uptime")).setExecutor(new Uptime());
|
||||
Objects
|
||||
.requireNonNull(getCommand("topplaytime"))
|
||||
.setExecutor(new TopTime());
|
||||
Objects
|
||||
.requireNonNull(this.getCommand("pt"))
|
||||
.setTabCompleter(new TimeTabCompleter());
|
||||
}
|
||||
|
||||
public void loadDatabase() {
|
||||
if (
|
||||
DataManager
|
||||
.getInstance()
|
||||
.getDBConfig()
|
||||
.getBoolean("database-settings.enabled")
|
||||
) {
|
||||
getLogger().info("Connecting to Database...");
|
||||
DatabaseManager databaseManager = DatabaseManager.getInstance();
|
||||
|
||||
try {
|
||||
if (databaseManager.getDataSource().getConnection() != null) {
|
||||
try {
|
||||
databaseManager.getDataSource().closeConnection();
|
||||
} catch (Exception e) {
|
||||
getLogger()
|
||||
.warning("Error while trying to close Database connection..");
|
||||
}
|
||||
databaseManager.load();
|
||||
|
||||
if (
|
||||
DataManager
|
||||
.getInstance()
|
||||
.getDBConfig()
|
||||
.getBoolean("purge-database.enabled")
|
||||
) databaseManager.purgeOldPlaytimeData();
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
getLogger().severe("Error loading the database: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void checkForUpdate() {
|
||||
Bukkit
|
||||
.getScheduler()
|
||||
.runTaskAsynchronously(
|
||||
this,
|
||||
() -> {
|
||||
UpdateChecker updater = new UpdateChecker(this, 58858);
|
||||
try {
|
||||
if (updater.hasUpdatesAvailable()) {
|
||||
getLogger()
|
||||
.warning(
|
||||
ChatUtil.format(
|
||||
"You are using an older version of PlayTimes!"
|
||||
)
|
||||
);
|
||||
getLogger()
|
||||
.info(ChatUtil.format("Download the newest version here:"));
|
||||
getLogger()
|
||||
.info(
|
||||
ChatUtil.format("https://www.spigotmc.org/resources/58858/")
|
||||
);
|
||||
} else {
|
||||
getLogger()
|
||||
.info(
|
||||
"[PlayTimes] Plugin is up to date! - " +
|
||||
getDescription().getVersion()
|
||||
);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
getLogger().warning("[PlayTimes] Could not check for updates!");
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,54 +1,44 @@
|
||||
package me.codedred.playtimes;
|
||||
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.URL;
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
public class UpdateChecker {
|
||||
|
||||
private static final String UPDATE_URL = "https://api.spigotmc.org/legacy/update.php?resource=%d";
|
||||
private static final String UPDATE_URL =
|
||||
"https://api.spigotmc.org/legacy/update.php?resource=%d";
|
||||
|
||||
private final JavaPlugin plugin;
|
||||
private final int projectId;
|
||||
private String cachedVersion;
|
||||
private final JavaPlugin plugin;
|
||||
private final int projectId;
|
||||
|
||||
public UpdateChecker(JavaPlugin plugin, int projectId) {
|
||||
this.plugin = Objects.requireNonNull(plugin, "Plugin cannot be null.");
|
||||
this.projectId = projectId;
|
||||
this.cachedVersion = plugin.getDescription().getVersion();
|
||||
public UpdateChecker(JavaPlugin plugin, int projectId) {
|
||||
this.plugin = Objects.requireNonNull(plugin, "Plugin cannot be null.");
|
||||
this.projectId = projectId;
|
||||
}
|
||||
|
||||
public boolean hasUpdatesAvailable() throws IOException {
|
||||
String latestVersion;
|
||||
|
||||
URL url = new URL(String.format(UPDATE_URL, projectId));
|
||||
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
|
||||
connection.setRequestMethod("GET");
|
||||
connection.setConnectTimeout(5000);
|
||||
connection.setReadTimeout(5000);
|
||||
connection.setUseCaches(true);
|
||||
|
||||
latestVersion =
|
||||
new BufferedReader(new InputStreamReader(connection.getInputStream()))
|
||||
.readLine();
|
||||
|
||||
if (latestVersion == null || latestVersion.isEmpty()) {
|
||||
throw new IOException("Failed to retrieve latest version.");
|
||||
}
|
||||
|
||||
public boolean checkForUpdates() throws IOException {
|
||||
String latestVersion = getCachedVersion();
|
||||
|
||||
if (latestVersion == null) {
|
||||
URL url = new URL(String.format(UPDATE_URL, projectId));
|
||||
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
|
||||
connection.setRequestMethod("GET");
|
||||
connection.setConnectTimeout(5000);
|
||||
connection.setReadTimeout(5000);
|
||||
connection.setUseCaches(true);
|
||||
|
||||
latestVersion = new BufferedReader(new InputStreamReader(connection.getInputStream()))
|
||||
.readLine();
|
||||
|
||||
if (latestVersion == null || latestVersion.isEmpty()) {
|
||||
throw new IOException("Failed to retrieve latest version.");
|
||||
}
|
||||
|
||||
cachedVersion = latestVersion;
|
||||
}
|
||||
|
||||
return !plugin.getDescription().getVersion().equals(cachedVersion);
|
||||
}
|
||||
|
||||
public String getCachedVersion() {
|
||||
return cachedVersion;
|
||||
}
|
||||
}
|
||||
return !plugin.getDescription().getVersion().equals(latestVersion);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package me.codedred.playtimes.api;
|
||||
|
||||
import java.util.UUID;
|
||||
import me.codedred.playtimes.statistics.StatManager;
|
||||
import me.codedred.playtimes.statistics.StatisticType;
|
||||
import me.codedred.playtimes.time.TimeManager;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class TimelessPlayer {
|
||||
|
||||
private final UUID uuid;
|
||||
private final StatManager stats;
|
||||
private final TimeManager timings;
|
||||
|
||||
public TimelessPlayer(final Player player) {
|
||||
this.uuid = player.getUniqueId();
|
||||
this.stats = StatManager.getInstance();
|
||||
this.timings = TimeManager.getInstance();
|
||||
}
|
||||
|
||||
public TimelessPlayer(final UUID player) {
|
||||
this.uuid = player;
|
||||
this.stats = StatManager.getInstance();
|
||||
this.timings = TimeManager.getInstance();
|
||||
}
|
||||
|
||||
public String getPlayTime() {
|
||||
return this.timings.buildFormat(
|
||||
this.stats.getPlayerStat(this.uuid, StatisticType.PLAYTIME) / 20L
|
||||
);
|
||||
}
|
||||
|
||||
public long getRawPlayTimeInSeconds() {
|
||||
return this.stats.getPlayerStat(this.uuid, StatisticType.PLAYTIME) / 20L;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
package me.codedred.playtimes.api;
|
||||
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import me.codedred.playtimes.models.Leaderboard;
|
||||
import me.codedred.playtimes.statistics.StatManager;
|
||||
|
||||
public class TimelessServer {
|
||||
|
||||
public List<UUID> getTop10Players() {
|
||||
final List<UUID> players = new ArrayList<>();
|
||||
final Leaderboard board = new Leaderboard();
|
||||
final Map<String, Integer> map = board.getTopTen();
|
||||
final Object[] array = map.keySet().toArray();
|
||||
for (int i = 0; i < map.size(); ++i) {
|
||||
players.add(UUID.fromString(array[i].toString()));
|
||||
}
|
||||
return players;
|
||||
}
|
||||
|
||||
public List<Integer> getTop10Times() {
|
||||
final List<Integer> players = new ArrayList<>();
|
||||
final Leaderboard board = new Leaderboard();
|
||||
final Map<String, Integer> map = board.getTopTen();
|
||||
final Object[] array = map.values().toArray();
|
||||
for (int i = 0; i < map.size(); ++i) {
|
||||
players.add(Integer.parseInt(array[i].toString()) / 20);
|
||||
}
|
||||
return players;
|
||||
}
|
||||
|
||||
public Map<String, Integer> getTopMap() {
|
||||
final Leaderboard board = new Leaderboard();
|
||||
return board.getTopTen();
|
||||
}
|
||||
|
||||
public UUID getNumberOne() {
|
||||
return this.getTop10Players().get(0);
|
||||
}
|
||||
|
||||
public UUID getNumberTwo() {
|
||||
return this.getTop10Players().get(1);
|
||||
}
|
||||
|
||||
public UUID getNumberThree() {
|
||||
return this.getTop10Players().get(2);
|
||||
}
|
||||
|
||||
public UUID getNumberFour() {
|
||||
return this.getTop10Players().get(3);
|
||||
}
|
||||
|
||||
public UUID getNumberFive() {
|
||||
return this.getTop10Players().get(4);
|
||||
}
|
||||
|
||||
public UUID getNumberSix() {
|
||||
return this.getTop10Players().get(5);
|
||||
}
|
||||
|
||||
public UUID getNumberSeven() {
|
||||
return this.getTop10Players().get(6);
|
||||
}
|
||||
|
||||
public UUID getNumberEight() {
|
||||
return this.getTop10Players().get(7);
|
||||
}
|
||||
|
||||
public UUID getNumberNine() {
|
||||
return this.getTop10Players().get(8);
|
||||
}
|
||||
|
||||
public UUID getNumberTen() {
|
||||
return this.getTop10Players().get(9);
|
||||
}
|
||||
|
||||
public String getUptime() {
|
||||
return StatManager.getInstance().getUptime();
|
||||
}
|
||||
|
||||
public long getUptimeInSeconds() {
|
||||
return TimeUnit.MILLISECONDS.toSeconds(
|
||||
ManagementFactory.getRuntimeMXBean().getUptime()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,9 @@
|
||||
package me.codedred.playtimes.commands;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import me.codedred.playtimes.PlayTimes;
|
||||
import me.codedred.playtimes.data.DataManager;
|
||||
import me.codedred.playtimes.player.OfflinePlayer;
|
||||
@@ -19,161 +23,226 @@ import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class Time implements CommandExecutor {
|
||||
|
||||
private final DataManager data = DataManager.getInstance();
|
||||
private final DataManager data = DataManager.getInstance();
|
||||
|
||||
public boolean onCommand(CommandSender sender, @NotNull Command cmd, @NotNull String label, String[] args) {
|
||||
if (!sender.hasPermission("pt.use")) {
|
||||
ChatUtil.errno(sender, ChatUtil.ChatTypes.NO_PERMISSION);
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (args.length > 0 ? args[0].toLowerCase() : "") {
|
||||
case "" -> handlePlayerCommand(sender);
|
||||
case "reload" -> handleReloadCommand(sender);
|
||||
case "top" -> handleTopCommand(sender);
|
||||
case "block" -> handleBlockCommand(sender, args, true);
|
||||
case "unblock" -> handleBlockCommand(sender, args, false);
|
||||
case "debug" -> handleDebugCommand(sender);
|
||||
case "help" -> handleHelpCommand(sender);
|
||||
default -> handleOtherPlayerCommand(sender, args);
|
||||
}
|
||||
return true;
|
||||
public boolean onCommand(
|
||||
CommandSender sender,
|
||||
@NotNull Command cmd,
|
||||
@NotNull String label,
|
||||
String[] args
|
||||
) {
|
||||
if (!sender.hasPermission("pt.use")) {
|
||||
ChatUtil.errno(sender, ChatUtil.ChatTypes.NO_PERMISSION);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void handleHelpCommand(CommandSender sender) {
|
||||
if (!sender.hasPermission("pt.reload")) {
|
||||
ChatUtil.errno(sender, ChatUtil.ChatTypes.NO_PERMISSION);
|
||||
return;
|
||||
}
|
||||
// assuming the main command is "pt"
|
||||
sender.sendMessage(ChatUtil.format("&6&l*** PlayTimes Help ***"));
|
||||
sender.sendMessage(ChatUtil.format("&e/pt: &7Displays your play time"));
|
||||
sender.sendMessage(ChatUtil.format("&e/pt reload: &7Reloads the PlayTimes plugin configurations"));
|
||||
sender.sendMessage(ChatUtil.format("&e/pt top: &7Shows the top players by play time"));
|
||||
sender.sendMessage(ChatUtil.format("&e/pt block <player>: &7Blocks a player from leaderboards"));
|
||||
sender.sendMessage(ChatUtil.format("&e/pt unblock <player>: &7Unblocks a player from leaderboards"));
|
||||
sender.sendMessage(ChatUtil.format("&e/pt debug: &7Displays the debug info"));
|
||||
sender.sendMessage(ChatUtil.format("&e/pt <player>: &7Displays the play time of <player>"));
|
||||
switch (args.length > 0 ? args[0].toLowerCase() : "") {
|
||||
case "" -> handlePlayerCommand(sender);
|
||||
case "reload" -> handleReloadCommand(sender);
|
||||
case "top" -> handleTopCommand(sender);
|
||||
case "block" -> handleBlockCommand(sender, args, true);
|
||||
case "unblock" -> handleBlockCommand(sender, args, false);
|
||||
case "debug" -> handleDebugCommand(sender);
|
||||
case "help" -> handleHelpCommand(sender);
|
||||
default -> handleOtherPlayerCommand(sender, args);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void handleDebugCommand(CommandSender sender) {
|
||||
if (!sender.hasPermission("pt.reload")) {
|
||||
ChatUtil.errno(sender, ChatUtil.ChatTypes.NO_PERMISSION);
|
||||
return;
|
||||
}
|
||||
boolean isOnline = ServerManager.getInstance().isOnline();
|
||||
String serverStatus = isOnline ? "Online" : "Offline";
|
||||
|
||||
sender.sendMessage(ChatUtil.format("&6&l*** PlayTimes Debug ***"));
|
||||
sender.sendMessage(ChatColor.GOLD + "Server version: " + ChatColor.WHITE + Bukkit.getServer().getVersion() +
|
||||
ChatColor.GOLD + "\nPlayTimes version: " + ChatColor.WHITE + JavaPlugin.getPlugin(PlayTimes.class).getDescription().getVersion() +
|
||||
ChatColor.GOLD + "\nStatManager: " + ChatColor.WHITE + StatManager.getInstance().name +
|
||||
ChatColor.GOLD + "\nServerStatus: " + ChatColor.WHITE + serverStatus);
|
||||
private void handleHelpCommand(CommandSender sender) {
|
||||
if (!sender.hasPermission("pt.reload")) {
|
||||
ChatUtil.errno(sender, ChatUtil.ChatTypes.NO_PERMISSION);
|
||||
return;
|
||||
}
|
||||
sender.sendMessage(ChatUtil.format("&6&l*** PlayTimes Help ***"));
|
||||
sender.sendMessage(ChatUtil.format("&e/pt: &7Displays your play time"));
|
||||
sender.sendMessage(
|
||||
ChatUtil.format(
|
||||
"&e/pt reload: &7Reloads the PlayTimes plugin configurations"
|
||||
)
|
||||
);
|
||||
sender.sendMessage(
|
||||
ChatUtil.format("&e/pt top: &7Shows the top players by play time")
|
||||
);
|
||||
sender.sendMessage(
|
||||
ChatUtil.format(
|
||||
"&e/pt block <player>: &7Blocks a player from leaderboards"
|
||||
)
|
||||
);
|
||||
sender.sendMessage(
|
||||
ChatUtil.format(
|
||||
"&e/pt unblock <player>: &7Unblocks a player from leaderboards"
|
||||
)
|
||||
);
|
||||
sender.sendMessage(
|
||||
ChatUtil.format("&e/pt debug: &7Displays the debug info")
|
||||
);
|
||||
sender.sendMessage(
|
||||
ChatUtil.format("&e/pt <player>: &7Displays the play time of <player>")
|
||||
);
|
||||
}
|
||||
|
||||
private void handlePlayerCommand(CommandSender sender) {
|
||||
if (!(sender instanceof Player)) {
|
||||
StatManager stats = StatManager.getInstance();
|
||||
sender.sendMessage(ChatUtil.format("&cThe console has been up for " + stats.getUptime()));
|
||||
return;
|
||||
private void handleDebugCommand(CommandSender sender) {
|
||||
if (!sender.hasPermission("pt.reload")) {
|
||||
ChatUtil.errno(sender, ChatUtil.ChatTypes.NO_PERMISSION);
|
||||
return;
|
||||
}
|
||||
boolean isOnline = ServerManager.getInstance().isOnline();
|
||||
String serverStatus = isOnline ? "Online" : "Offline";
|
||||
|
||||
sender.sendMessage(ChatUtil.format("&6&l*** PlayTimes Debug ***"));
|
||||
sender.sendMessage(
|
||||
ChatColor.GOLD +
|
||||
"Server version: " +
|
||||
ChatColor.WHITE +
|
||||
Bukkit.getServer().getVersion() +
|
||||
ChatColor.GOLD +
|
||||
"\nPlayTimes version: " +
|
||||
ChatColor.WHITE +
|
||||
JavaPlugin.getPlugin(PlayTimes.class).getDescription().getVersion() +
|
||||
ChatColor.GOLD +
|
||||
"\nStatManager: " +
|
||||
ChatColor.WHITE +
|
||||
StatManager.getInstance().name +
|
||||
ChatColor.GOLD +
|
||||
"\nServerStatus: " +
|
||||
ChatColor.WHITE +
|
||||
serverStatus
|
||||
);
|
||||
}
|
||||
|
||||
private void handlePlayerCommand(CommandSender sender) {
|
||||
if (!(sender instanceof Player)) {
|
||||
StatManager stats = StatManager.getInstance();
|
||||
sender.sendMessage(
|
||||
ChatUtil.format("&cThe console has been up for " + stats.getUptime())
|
||||
);
|
||||
return;
|
||||
}
|
||||
OnlinePlayer player = new OnlinePlayer((Player) sender);
|
||||
player.sendMessageToTarget();
|
||||
}
|
||||
|
||||
private void handleReloadCommand(CommandSender sender) {
|
||||
if (!sender.hasPermission("pt.reload")) {
|
||||
ChatUtil.errno(sender, ChatUtil.ChatTypes.NO_PERMISSION);
|
||||
return;
|
||||
}
|
||||
data.reloadAll();
|
||||
TimeConstants.reload();
|
||||
TimeManager.getInstance().registerTimings();
|
||||
sender.sendMessage(ChatUtil.format("&aPlayTimes Configurations Reloaded!"));
|
||||
}
|
||||
|
||||
private void handleTopCommand(CommandSender sender) {
|
||||
Bukkit.dispatchCommand(sender, "toppt");
|
||||
}
|
||||
|
||||
private void handleBlockCommand(
|
||||
CommandSender sender,
|
||||
String[] args,
|
||||
boolean block
|
||||
) {
|
||||
String blockAction = block ? "block" : "unblock";
|
||||
if (!sender.hasPermission("pt.block")) {
|
||||
ChatUtil.errno(sender, ChatUtil.ChatTypes.NO_PERMISSION);
|
||||
return;
|
||||
}
|
||||
if (args.length < 2) {
|
||||
sender.sendMessage(
|
||||
ChatUtil.formatWithPrefix(
|
||||
"&c&lIncorrect Usage&c, try &7/pt " + blockAction + " <player>"
|
||||
)
|
||||
);
|
||||
return;
|
||||
}
|
||||
String playerName = args[1];
|
||||
String blockedKey = "blocked." + playerName.toLowerCase();
|
||||
if (block == data.getData().contains(blockedKey)) {
|
||||
sender.sendMessage(
|
||||
ChatUtil.formatWithPrefix("&cUser is already " + blockAction + "ed!")
|
||||
);
|
||||
sender.sendMessage(
|
||||
ChatUtil.formatWithPrefix(
|
||||
"&c&oMaybe try, &7/pt " + (block ? "unblock" : "block") + " <player>"
|
||||
)
|
||||
);
|
||||
return;
|
||||
}
|
||||
UUID uuid;
|
||||
if (Bukkit.getPlayer(playerName) == null) {
|
||||
try {
|
||||
uuid = ServerManager.getInstance().getUUID(playerName.toLowerCase());
|
||||
} catch (NullPointerException e) {
|
||||
ChatUtil.errno(sender, ChatUtil.ChatTypes.PLAYER_NOT_FOUND);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
uuid = Objects.requireNonNull(Bukkit.getPlayer(playerName)).getUniqueId();
|
||||
}
|
||||
if (uuid == null) {
|
||||
sender.sendMessage(ChatUtil.formatWithPrefix("&c&lUser not found."));
|
||||
return;
|
||||
}
|
||||
if (block) {
|
||||
data.getData().set(blockedKey, uuid.toString());
|
||||
if (data.getData().contains("leaderboard." + uuid)) {
|
||||
data.getData().set("leaderboard." + uuid, null);
|
||||
}
|
||||
sender.sendMessage(
|
||||
ChatUtil.formatWithPrefix("&aUser &c&lBLOCKED &afrom leaderboards!")
|
||||
);
|
||||
} else {
|
||||
data.getData().set(blockedKey, null);
|
||||
sender.sendMessage(
|
||||
ChatUtil.formatWithPrefix("&aUser &b&lUNBLOCKED &afrom leaderboards!")
|
||||
);
|
||||
}
|
||||
data.saveData();
|
||||
}
|
||||
|
||||
private void handleOtherPlayerCommand(CommandSender sender, String[] args) {
|
||||
if (!sender.hasPermission("pt.others")) {
|
||||
ChatUtil.errno(sender, ChatUtil.ChatTypes.NO_PERMISSION);
|
||||
return;
|
||||
}
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Pattern p = Pattern.compile("[^a-z0-9_]", Pattern.CASE_INSENSITIVE);
|
||||
Matcher m = p.matcher(args[0]);
|
||||
boolean b = m.find();
|
||||
|
||||
if (b) {
|
||||
ChatUtil.errno(sender, ChatUtil.ChatTypes.PLAYER_NOT_FOUND);
|
||||
return;
|
||||
}
|
||||
OnlinePlayer player = new OnlinePlayer((Player) sender);
|
||||
|
||||
UUID target;
|
||||
if (Bukkit.getPlayer(args[0]) == null) {
|
||||
target = ServerManager.getInstance().getUUID(args[0]);
|
||||
if (target == null) {
|
||||
ChatUtil.errno(sender, ChatUtil.ChatTypes.PLAYER_NOT_FOUND);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
target =
|
||||
Objects.requireNonNull(Bukkit.getPlayer(args[0])).getUniqueId();
|
||||
}
|
||||
|
||||
org.bukkit.OfflinePlayer offlinePlayer = Bukkit
|
||||
.getServer()
|
||||
.getOfflinePlayer(target);
|
||||
OfflinePlayer player = new OfflinePlayer(
|
||||
sender,
|
||||
target,
|
||||
offlinePlayer.getName()
|
||||
);
|
||||
player.sendMessageToTarget();
|
||||
}
|
||||
}
|
||||
|
||||
private void handleReloadCommand(CommandSender sender) {
|
||||
if (!sender.hasPermission("pt.reload")) {
|
||||
ChatUtil.errno(sender, ChatUtil.ChatTypes.NO_PERMISSION);
|
||||
return;
|
||||
}
|
||||
data.reloadAll();
|
||||
TimeConstants.reload();
|
||||
TimeManager.getInstance().registerTimings();
|
||||
sender.sendMessage(ChatUtil.format("&aPlayTimes Configurations Reloaded!"));
|
||||
}
|
||||
|
||||
private void handleTopCommand(CommandSender sender) {
|
||||
Bukkit.dispatchCommand(sender, "toppt");
|
||||
}
|
||||
|
||||
private void handleBlockCommand(CommandSender sender, String[] args, boolean block) {
|
||||
String blockAction = block ? "block" : "unblock";
|
||||
if (!sender.hasPermission("pt.block")) {
|
||||
ChatUtil.errno(sender, ChatUtil.ChatTypes.NO_PERMISSION);
|
||||
return;
|
||||
}
|
||||
if (args.length < 2) {
|
||||
sender.sendMessage(ChatUtil.formatWithPrefix("&c&lIncorrect Usage&c, try &7/pt " + blockAction + " <player>"));
|
||||
return;
|
||||
}
|
||||
String playerName = args[1];
|
||||
String blockedKey = "blocked." + playerName.toLowerCase();
|
||||
if (block == data.getData().contains(blockedKey)) {
|
||||
sender.sendMessage(ChatUtil.formatWithPrefix("&cUser is already " + blockAction + "ed!"));
|
||||
sender.sendMessage(ChatUtil.formatWithPrefix("&c&oMaybe try, &7/pt " + (block ? "unblock" : "block") + " <player>"));
|
||||
return;
|
||||
}
|
||||
UUID uuid;
|
||||
if (Bukkit.getPlayer(playerName) == null) {
|
||||
try {
|
||||
uuid = ServerManager.getInstance().getUUID(playerName.toLowerCase());
|
||||
} catch (NullPointerException e) {
|
||||
ChatUtil.errno(sender, ChatUtil.ChatTypes.PLAYER_NOT_FOUND);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
uuid = Objects.requireNonNull(Bukkit.getPlayer(playerName)).getUniqueId();
|
||||
}
|
||||
if (block) {
|
||||
data.getData().set(blockedKey, uuid.toString());
|
||||
if (data.getData().contains("leaderboard." + uuid)) {
|
||||
data.getData().set("leaderboard." + uuid, null);
|
||||
}
|
||||
sender.sendMessage(ChatUtil.formatWithPrefix("&aUser &c&lBLOCKED &afrom leaderboards!"));
|
||||
} else {
|
||||
data.getData().set(blockedKey, null);
|
||||
sender.sendMessage(ChatUtil.formatWithPrefix("&aUser &b&lUNBLOCKED &afrom leaderboards!"));
|
||||
}
|
||||
data.saveData();
|
||||
}
|
||||
|
||||
private void handleOtherPlayerCommand(CommandSender sender, String[] args) {
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Pattern p = Pattern.compile("[^a-z0-9_]", Pattern.CASE_INSENSITIVE);
|
||||
Matcher m = p.matcher(args[0]);
|
||||
boolean b = m.find();
|
||||
|
||||
if (b) {
|
||||
ChatUtil.errno(sender, ChatUtil.ChatTypes.PLAYER_NOT_FOUND);
|
||||
return;
|
||||
}
|
||||
|
||||
UUID target;
|
||||
if (Bukkit.getPlayer(args[0]) == null) {
|
||||
target = ServerManager.getInstance().getUUID(args[0]);
|
||||
if (target == null) {
|
||||
ChatUtil.errno(sender, ChatUtil.ChatTypes.PLAYER_NOT_FOUND);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
target = Objects.requireNonNull(Bukkit.getPlayer(args[0])).getUniqueId();
|
||||
}
|
||||
|
||||
org.bukkit.OfflinePlayer offlinePlayer = Bukkit.getServer().getOfflinePlayer(target);
|
||||
OfflinePlayer player = new OfflinePlayer(sender, target, offlinePlayer.getName());
|
||||
player.sendMessageToTarget();
|
||||
}
|
||||
}.runTaskAsynchronously(JavaPlugin.getPlugin(PlayTimes.class));
|
||||
}
|
||||
.runTaskAsynchronously(JavaPlugin.getPlugin(PlayTimes.class));
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,10 @@
|
||||
package me.codedred.playtimes.commands;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
import me.codedred.playtimes.data.DataManager;
|
||||
import me.codedred.playtimes.models.Leaderboard;
|
||||
import me.codedred.playtimes.statistics.StatManager;
|
||||
import me.codedred.playtimes.time.TimeManager;
|
||||
import me.codedred.playtimes.utils.*;
|
||||
@@ -9,90 +13,116 @@ import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import me.codedred.playtimes.models.Leaderboard;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
public class TopTime implements CommandExecutor {
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, @NotNull Command cmd, @NotNull String label, String[] args) {
|
||||
if (!sender.hasPermission("pt.top")) {
|
||||
ChatUtil.errno(sender, ChatUtil.ChatTypes.NO_PERMISSION);
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public boolean onCommand(
|
||||
CommandSender sender,
|
||||
@NotNull Command cmd,
|
||||
@NotNull String label,
|
||||
String[] args
|
||||
) {
|
||||
if (!sender.hasPermission("pt.top")) {
|
||||
ChatUtil.errno(sender, ChatUtil.ChatTypes.NO_PERMISSION);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(sender instanceof Player player)) {
|
||||
sender.sendMessage("Must be a player to run this command.");
|
||||
return true;
|
||||
}
|
||||
if (!(sender instanceof Player player)) {
|
||||
sender.sendMessage("Must be a player to run this command.");
|
||||
return true;
|
||||
}
|
||||
|
||||
DataManager data = DataManager.getInstance();
|
||||
DataManager data = DataManager.getInstance();
|
||||
|
||||
if (data.getConfig().getBoolean("top-playtime.enable-cooldown") && !player.hasPermission("pt.block-cooldown")) {
|
||||
if (CoolDownUtil.contains(player.getUniqueId())) {
|
||||
String cooldownMessage = Objects.requireNonNull(data.getConfig().getString("messages.cooldown"))
|
||||
.replace("%timeleft%", Integer.toString(CoolDownUtil.left(player.getUniqueId())));
|
||||
sender.sendMessage(ChatUtil.formatWithPrefix(cooldownMessage));
|
||||
return true;
|
||||
}
|
||||
CoolDownUtil.add(player.getUniqueId(), System.currentTimeMillis() + (data.getConfig().getInt("top-playtime.cooldown-seconds") * 1000L));
|
||||
}
|
||||
if (
|
||||
data.getConfig().getBoolean("top-playtime.enable-cooldown") &&
|
||||
!player.hasPermission("pt.block-cooldown")
|
||||
) {
|
||||
if (CoolDownUtil.contains(player.getUniqueId())) {
|
||||
String cooldownMessage = Objects
|
||||
.requireNonNull(data.getConfig().getString("messages.cooldown"))
|
||||
.replace(
|
||||
"%timeleft%",
|
||||
Integer.toString(CoolDownUtil.left(player.getUniqueId()))
|
||||
);
|
||||
sender.sendMessage(ChatUtil.formatWithPrefix(cooldownMessage));
|
||||
return true;
|
||||
}
|
||||
CoolDownUtil.add(
|
||||
player.getUniqueId(),
|
||||
System.currentTimeMillis() +
|
||||
(data.getConfig().getInt("top-playtime.cooldown-seconds") * 1000L)
|
||||
);
|
||||
}
|
||||
|
||||
Leaderboard board = new Leaderboard();
|
||||
Map<String, Integer> map = board.getTopTen();
|
||||
Leaderboard board = new Leaderboard();
|
||||
Map<String, Integer> map = board.getTopTen();
|
||||
|
||||
if (map.isEmpty()) {
|
||||
sender.sendMessage(ChatUtil.format("&cRejoin the server to fill the leaderboard!"));
|
||||
return true;
|
||||
}
|
||||
if (map.isEmpty()) {
|
||||
sender.sendMessage(
|
||||
ChatUtil.format("&cRejoin the server to fill the leaderboard!")
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
StatManager statManager = StatManager.getInstance();
|
||||
TimeManager timeManager = TimeManager.getInstance();
|
||||
String header = ChatUtil.format(data.getConfig().getString("top-playtime.header"));
|
||||
String footer = ChatUtil.format(data.getConfig().getString("top-playtime.footer"));
|
||||
String content = data.getConfig().getString("top-playtime.content");
|
||||
StatManager statManager = StatManager.getInstance();
|
||||
TimeManager timeManager = TimeManager.getInstance();
|
||||
String header = ChatUtil.format(
|
||||
data.getConfig().getString("top-playtime.header")
|
||||
);
|
||||
String footer = ChatUtil.format(
|
||||
data.getConfig().getString("top-playtime.footer")
|
||||
);
|
||||
String content = data.getConfig().getString("top-playtime.content");
|
||||
|
||||
if (ServerUtils.hasPAPI()) {
|
||||
header = PAPIHolders.getHolders(player, header);
|
||||
footer = PAPIHolders.getHolders(player, footer);
|
||||
}
|
||||
if (ServerUtils.hasPAPI()) {
|
||||
header = PAPIHolders.getHolders(player, header);
|
||||
footer = PAPIHolders.getHolders(player, footer);
|
||||
}
|
||||
|
||||
sender.sendMessage(header);
|
||||
sender.sendMessage(header);
|
||||
|
||||
for (int i = 0; i < map.size(); i++) {
|
||||
UUID uuid = UUID.fromString(map.keySet().toArray()[i].toString());
|
||||
org.bukkit.OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(uuid);
|
||||
for (int i = 0; i < map.size(); i++) {
|
||||
UUID uuid = UUID.fromString(map.keySet().toArray()[i].toString());
|
||||
org.bukkit.OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(uuid);
|
||||
|
||||
if (ServerUtils.hasPAPI()) {
|
||||
content = PAPIHolders.getHolders(offlinePlayer, content);
|
||||
}
|
||||
if (ServerUtils.hasPAPI()) {
|
||||
content = PAPIHolders.getHolders(offlinePlayer, content);
|
||||
}
|
||||
|
||||
String offlinePlayerName = offlinePlayer.getName();
|
||||
String place = String.valueOf(i + 1);
|
||||
String time = timeManager.buildFormat(map.get(offlinePlayer.getUniqueId().toString()) / 20);
|
||||
String joinDate = statManager.getJoinDate(uuid);
|
||||
String defaultPlayerName = "Unknown";
|
||||
String defaultJoinDate = "N/A";
|
||||
String defaultTime = "0h 0m 0s";
|
||||
|
||||
if (time == null) {
|
||||
continue;
|
||||
}
|
||||
String offlinePlayerName = offlinePlayer.getName() != null
|
||||
? offlinePlayer.getName()
|
||||
: defaultPlayerName;
|
||||
String place = String.valueOf(i + 1);
|
||||
String time = timeManager.buildFormat(
|
||||
map.get(offlinePlayer.getUniqueId().toString()) / 20
|
||||
);
|
||||
String joinDate = statManager.getJoinDate(uuid) != null
|
||||
? statManager.getJoinDate(uuid)
|
||||
: defaultJoinDate;
|
||||
|
||||
sender.sendMessage(ChatUtil.format(content
|
||||
.replace("%player%", offlinePlayerName)
|
||||
.replace("%place%", place)
|
||||
.replace("%time%", time)
|
||||
.replace("%joindate%", joinDate)));
|
||||
if (time == null) {
|
||||
time = defaultTime;
|
||||
}
|
||||
|
||||
content = data.getConfig().getString("top-playtime.content");
|
||||
}
|
||||
|
||||
sender.sendMessage(footer);
|
||||
return true;
|
||||
}
|
||||
String formattedContent = content
|
||||
.replace("%player%", offlinePlayerName)
|
||||
.replace("%place%", place)
|
||||
.replace("%time%", time)
|
||||
.replace("%joindate%", joinDate);
|
||||
|
||||
sender.sendMessage(ChatUtil.format(formattedContent));
|
||||
|
||||
content = data.getConfig().getString("top-playtime.content");
|
||||
}
|
||||
|
||||
sender.sendMessage(footer);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package me.codedred.playtimes.commands;
|
||||
|
||||
import java.util.List;
|
||||
import me.clip.placeholderapi.PlaceholderAPI;
|
||||
import me.codedred.playtimes.data.DataManager;
|
||||
import me.codedred.playtimes.statistics.StatManager;
|
||||
@@ -12,37 +13,53 @@ import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class Uptime implements CommandExecutor {
|
||||
|
||||
@Override
|
||||
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command cmd, String cmdL, String[] args) {
|
||||
if (!cmdL.equalsIgnoreCase("uptime") && !cmdL.equalsIgnoreCase("serveruptime") && !cmdL.equalsIgnoreCase("serverupt")) {
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public boolean onCommand(
|
||||
@NotNull CommandSender sender,
|
||||
@NotNull Command cmd,
|
||||
String cmdL,
|
||||
String[] args
|
||||
) {
|
||||
if (
|
||||
!cmdL.equalsIgnoreCase("uptime") &&
|
||||
!cmdL.equalsIgnoreCase("serveruptime") &&
|
||||
!cmdL.equalsIgnoreCase("serverupt")
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!sender.hasPermission("pt.uptime")) {
|
||||
ChatUtil.errno(sender, ChatUtil.ChatTypes.NO_PERMISSION);
|
||||
return true;
|
||||
}
|
||||
if (!sender.hasPermission("pt.uptime")) {
|
||||
ChatUtil.errno(sender, ChatUtil.ChatTypes.NO_PERMISSION);
|
||||
return true;
|
||||
}
|
||||
|
||||
String uptime = StatManager.getInstance().getUptime();
|
||||
List<String> messages = DataManager.getInstance().getConfig().getStringList("uptime.message");
|
||||
String uptime = StatManager.getInstance().getUptime();
|
||||
List<String> messages = DataManager
|
||||
.getInstance()
|
||||
.getConfig()
|
||||
.getStringList("uptime.message");
|
||||
|
||||
for (String message : messages) {
|
||||
if (ServerUtils.hasPAPI() && sender instanceof Player player) {
|
||||
message = PlaceholderAPI.setPlaceholders(player, message);
|
||||
}
|
||||
for (String message : messages) {
|
||||
if (ServerUtils.hasPAPI() && sender instanceof Player player) {
|
||||
message = PlaceholderAPI.setPlaceholders(player, message);
|
||||
}
|
||||
|
||||
if (message.contains("{\"text\":")) {
|
||||
String consoleCommand = "tellraw " + sender.getName() + " " + message.replace("%serveruptime%", uptime);
|
||||
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), consoleCommand);
|
||||
} else {
|
||||
sender.sendMessage(ChatUtil.format(message.replace("%serveruptime%", uptime)));
|
||||
}
|
||||
}
|
||||
if (message.contains("{\"text\":")) {
|
||||
String consoleCommand =
|
||||
"tellraw " +
|
||||
sender.getName() +
|
||||
" " +
|
||||
message.replace("%serveruptime%", uptime);
|
||||
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), consoleCommand);
|
||||
} else {
|
||||
sender.sendMessage(
|
||||
ChatUtil.format(message.replace("%serveruptime%", uptime))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
package me.codedred.playtimes.commands.completer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
@@ -7,40 +9,41 @@ import org.bukkit.command.TabCompleter;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class TimeTabCompleter implements TabCompleter {
|
||||
|
||||
@Override
|
||||
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, String[] args) {
|
||||
List<String> completions = new ArrayList<>();
|
||||
|
||||
if (args.length == 1) {
|
||||
if (sender.hasPermission("pt.use")) {
|
||||
completions.add("top");
|
||||
completions.addAll(getOnlinePlayerNames());
|
||||
}
|
||||
if (sender.hasPermission("pt.block")) {
|
||||
completions.add("block");
|
||||
completions.add("unblock");
|
||||
}
|
||||
if (sender.hasPermission("pt.reload")) {
|
||||
completions.add("reload");
|
||||
completions.add("debug");
|
||||
completions.add("help");
|
||||
}
|
||||
}
|
||||
|
||||
return completions;
|
||||
@Override
|
||||
public List<String> onTabComplete(
|
||||
@NotNull CommandSender sender,
|
||||
@NotNull Command command,
|
||||
@NotNull String alias,
|
||||
String[] args
|
||||
) {
|
||||
List<String> completions = new ArrayList<>();
|
||||
|
||||
if (args.length == 1) {
|
||||
if (sender.hasPermission("pt.use")) {
|
||||
completions.add("top");
|
||||
completions.addAll(getOnlinePlayerNames());
|
||||
}
|
||||
if (sender.hasPermission("pt.block")) {
|
||||
completions.add("block");
|
||||
completions.add("unblock");
|
||||
}
|
||||
if (sender.hasPermission("pt.reload")) {
|
||||
completions.add("reload");
|
||||
completions.add("debug");
|
||||
completions.add("help");
|
||||
}
|
||||
}
|
||||
|
||||
private List<String> getOnlinePlayerNames() {
|
||||
List<String> playerNames = new ArrayList<>();
|
||||
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||
playerNames.add(player.getName());
|
||||
}
|
||||
return playerNames;
|
||||
return completions;
|
||||
}
|
||||
|
||||
private List<String> getOnlinePlayerNames() {
|
||||
List<String> playerNames = new ArrayList<>();
|
||||
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||
playerNames.add(player.getName());
|
||||
}
|
||||
return playerNames;
|
||||
}
|
||||
}
|
||||
@@ -1,61 +1,64 @@
|
||||
package me.codedred.playtimes.data;
|
||||
|
||||
import me.codedred.playtimes.PlayTimes;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.logging.Level;
|
||||
import me.codedred.playtimes.PlayTimes;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
|
||||
public class CustomConfig {
|
||||
private final String name;
|
||||
private final PlayTimes plugin;
|
||||
private FileConfiguration dataConfig = null;
|
||||
private File dataConfigFile = null;
|
||||
|
||||
public CustomConfig(PlayTimes plugin, String fileName) {
|
||||
this.plugin = plugin;
|
||||
this.name = fileName;
|
||||
saveDefaultConfig();
|
||||
}
|
||||
private final String name;
|
||||
private final PlayTimes plugin;
|
||||
private FileConfiguration dataConfig = null;
|
||||
private File dataConfigFile = null;
|
||||
|
||||
public void reloadConfig() {
|
||||
if (this.dataConfigFile == null)
|
||||
this.dataConfigFile = new File(this.plugin.getDataFolder(), name);
|
||||
public CustomConfig(PlayTimes plugin, String fileName) {
|
||||
this.plugin = plugin;
|
||||
this.name = fileName;
|
||||
saveDefaultConfig();
|
||||
}
|
||||
|
||||
this.dataConfig = YamlConfiguration.loadConfiguration(this.dataConfigFile);
|
||||
public void reloadConfig() {
|
||||
if (this.dataConfigFile == null) this.dataConfigFile =
|
||||
new File(this.plugin.getDataFolder(), name);
|
||||
|
||||
InputStream defConfigStream = this.plugin.getResource(name);
|
||||
if (defConfigStream != null) {
|
||||
YamlConfiguration defConfig = YamlConfiguration
|
||||
.loadConfiguration(new InputStreamReader(defConfigStream));
|
||||
this.dataConfig.setDefaults(defConfig);
|
||||
}
|
||||
}
|
||||
this.dataConfig = YamlConfiguration.loadConfiguration(this.dataConfigFile);
|
||||
|
||||
public FileConfiguration getConfig() {
|
||||
if (this.dataConfig == null)
|
||||
reloadConfig();
|
||||
return this.dataConfig;
|
||||
}
|
||||
InputStream defConfigStream = this.plugin.getResource(name);
|
||||
if (defConfigStream != null) {
|
||||
YamlConfiguration defConfig = YamlConfiguration.loadConfiguration(
|
||||
new InputStreamReader(defConfigStream)
|
||||
);
|
||||
this.dataConfig.setDefaults(defConfig);
|
||||
}
|
||||
}
|
||||
|
||||
public void saveConfig() {
|
||||
if ((this.dataConfig == null) || (this.dataConfigFile == null))
|
||||
return;
|
||||
try {
|
||||
getConfig().save(this.dataConfigFile);
|
||||
} catch (IOException ex) {
|
||||
this.plugin.getLogger().log(Level.SEVERE, ex, () -> "Could not save config to " + this.dataConfigFile); }
|
||||
}
|
||||
public FileConfiguration getConfig() {
|
||||
if (this.dataConfig == null) reloadConfig();
|
||||
return this.dataConfig;
|
||||
}
|
||||
|
||||
public void saveDefaultConfig() {
|
||||
if (this.dataConfigFile == null)
|
||||
this.dataConfigFile = new File(this.plugin.getDataFolder(), name);
|
||||
if (!this.dataConfigFile.exists())
|
||||
this.plugin.saveResource(name, false);
|
||||
}
|
||||
public void saveConfig() {
|
||||
if ((this.dataConfig == null) || (this.dataConfigFile == null)) return;
|
||||
try {
|
||||
getConfig().save(this.dataConfigFile);
|
||||
} catch (IOException ex) {
|
||||
this.plugin.getLogger()
|
||||
.log(
|
||||
Level.SEVERE,
|
||||
ex,
|
||||
() -> "Could not save config to " + this.dataConfigFile
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
public void saveDefaultConfig() {
|
||||
if (this.dataConfigFile == null) this.dataConfigFile =
|
||||
new File(this.plugin.getDataFolder(), name);
|
||||
if (!this.dataConfigFile.exists()) this.plugin.saveResource(name, false);
|
||||
}
|
||||
}
|
||||
@@ -6,30 +6,43 @@ import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
public class DataManager {
|
||||
|
||||
private static final DataManager instance = new DataManager();
|
||||
private final CustomConfig data = new CustomConfig(JavaPlugin.getPlugin(PlayTimes.class), "data.yml");
|
||||
private final CustomConfig cfg = new CustomConfig(JavaPlugin.getPlugin(PlayTimes.class), "config.yml");
|
||||
private static final DataManager instance = new DataManager();
|
||||
private final CustomConfig data = new CustomConfig(
|
||||
JavaPlugin.getPlugin(PlayTimes.class),
|
||||
"data.yml"
|
||||
);
|
||||
private final CustomConfig db = new CustomConfig(
|
||||
JavaPlugin.getPlugin(PlayTimes.class),
|
||||
"database.yml"
|
||||
);
|
||||
private final CustomConfig cfg = new CustomConfig(
|
||||
JavaPlugin.getPlugin(PlayTimes.class),
|
||||
"config.yml"
|
||||
);
|
||||
|
||||
public static DataManager getInstance() {
|
||||
return instance;
|
||||
}
|
||||
public static DataManager getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
public FileConfiguration getConfig() {
|
||||
return cfg.getConfig();
|
||||
}
|
||||
public FileConfiguration getConfig() {
|
||||
return cfg.getConfig();
|
||||
}
|
||||
|
||||
public FileConfiguration getData() {
|
||||
return data.getConfig();
|
||||
}
|
||||
public FileConfiguration getData() {
|
||||
return data.getConfig();
|
||||
}
|
||||
|
||||
public void reloadAll() {
|
||||
data.reloadConfig();
|
||||
cfg.reloadConfig();
|
||||
}
|
||||
|
||||
public void saveData() {
|
||||
data.saveConfig();
|
||||
}
|
||||
public FileConfiguration getDBConfig() {
|
||||
return db.getConfig();
|
||||
}
|
||||
|
||||
public void saveData() {
|
||||
data.saveConfig();
|
||||
}
|
||||
|
||||
public void reloadAll() {
|
||||
data.reloadConfig();
|
||||
cfg.reloadConfig();
|
||||
db.reloadConfig();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package me.codedred.playtimes.data.database.datasource;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
|
||||
public interface DataSource {
|
||||
Connection getConnection() throws SQLException;
|
||||
|
||||
void closeConnection() throws SQLException;
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package me.codedred.playtimes.data.database.datasource.impl;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.SQLException;
|
||||
import lombok.val;
|
||||
import me.codedred.playtimes.PlayTimes;
|
||||
import me.codedred.playtimes.data.DataManager;
|
||||
import me.codedred.playtimes.data.database.datasource.DataSource;
|
||||
|
||||
public class MySQL implements DataSource {
|
||||
|
||||
private final String connectionUrl;
|
||||
private final String user;
|
||||
private final String password;
|
||||
|
||||
public MySQL(PlayTimes plugin) {
|
||||
val config = DataManager
|
||||
.getInstance()
|
||||
.getDBConfig()
|
||||
.getConfigurationSection("database-settings");
|
||||
val host = config.getString("host");
|
||||
val port = config.getString("port");
|
||||
this.user = config.getString("user");
|
||||
this.password = config.getString("password");
|
||||
val database = config.getString("database");
|
||||
val SSL = config.getBoolean("useSSL");
|
||||
|
||||
this.connectionUrl =
|
||||
String.format(
|
||||
"jdbc:mysql://%s:%s/%s?autoReconnect=true&useSSL=" + SSL,
|
||||
host,
|
||||
port,
|
||||
database
|
||||
);
|
||||
|
||||
try {
|
||||
Class.forName("com.mysql.cj.jdbc.Driver");
|
||||
plugin.getLogger().info("Successfully connected to database.");
|
||||
} catch (ClassNotFoundException e) {
|
||||
plugin
|
||||
.getLogger()
|
||||
.severe("MySQL JDBC Driver not found: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Connection getConnection() throws SQLException {
|
||||
return DriverManager.getConnection(connectionUrl, user, password);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeConnection() throws SQLException {
|
||||
// connection.close();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package me.codedred.playtimes.data.database.datasource.impl;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.SQLException;
|
||||
import lombok.val;
|
||||
import me.codedred.playtimes.PlayTimes;
|
||||
import me.codedred.playtimes.data.DataManager;
|
||||
import me.codedred.playtimes.data.database.datasource.DataSource;
|
||||
|
||||
public class SQLite implements DataSource {
|
||||
|
||||
private Connection connection;
|
||||
|
||||
public SQLite(PlayTimes plugin) {
|
||||
val config = DataManager.getInstance().getDBConfig();
|
||||
val database = config.getString("database");
|
||||
|
||||
try {
|
||||
Class.forName("org.sqlite.JDBC");
|
||||
String url =
|
||||
"jdbc:sqlite:" + plugin.getDataFolder() + "/" + database + ".db";
|
||||
this.connection = DriverManager.getConnection(url);
|
||||
plugin.getLogger().info("Successfully connected to database.");
|
||||
} catch (SQLException | ClassNotFoundException exception) {
|
||||
plugin
|
||||
.getLogger()
|
||||
.severe(
|
||||
"ERROR! Database failed to connect. Please check your config.yml and try again."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Connection getConnection() {
|
||||
return connection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeConnection() throws SQLException {
|
||||
connection.close();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
package me.codedred.playtimes.data.database.manager;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import lombok.Getter;
|
||||
import me.codedred.playtimes.PlayTimes;
|
||||
import me.codedred.playtimes.data.DataManager;
|
||||
import me.codedred.playtimes.data.database.datasource.DataSource;
|
||||
import me.codedred.playtimes.data.database.datasource.impl.MySQL;
|
||||
import me.codedred.playtimes.data.database.datasource.impl.SQLite;
|
||||
import me.codedred.playtimes.data.database.table.UsersTable;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
@Getter
|
||||
public class DatabaseManager {
|
||||
|
||||
private static DatabaseManager instance;
|
||||
|
||||
private DataSource dataSource;
|
||||
private UsersTable usersTable;
|
||||
|
||||
private Map<UUID, Map<String, Long>> userPlaytimes = new HashMap<>();
|
||||
|
||||
private DatabaseManager() {
|
||||
setupDataSource();
|
||||
}
|
||||
|
||||
public static DatabaseManager getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new DatabaseManager();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
private void setupDataSource() {
|
||||
String type = DataManager
|
||||
.getInstance()
|
||||
.getDBConfig()
|
||||
.getString("database-settings.type");
|
||||
|
||||
switch (type.toLowerCase()) {
|
||||
case "mysql":
|
||||
this.dataSource = new MySQL(PlayTimes.getPlugin(PlayTimes.class));
|
||||
break;
|
||||
case "sqlite":
|
||||
this.dataSource = new SQLite(PlayTimes.getPlugin(PlayTimes.class));
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException(
|
||||
"Unexpected database type: " +
|
||||
type +
|
||||
". Accepted Values: 'mysql', 'sqlite'"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public void load() {
|
||||
try {
|
||||
if (dataSource.getConnection() != null) {
|
||||
this.usersTable = new UsersTable(dataSource);
|
||||
this.usersTable.createTable();
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private UsersTable getUsersTable() {
|
||||
if (this.usersTable == null) {
|
||||
this.usersTable = new UsersTable(dataSource);
|
||||
}
|
||||
return this.usersTable;
|
||||
}
|
||||
|
||||
// Called onPlayerJoin
|
||||
public void retrievePlayTime(UUID uuid) {
|
||||
Map<String, Long> timeMap = getUsersTable().getPlaytimesByUuid(uuid);
|
||||
userPlaytimes.put(uuid, timeMap);
|
||||
}
|
||||
|
||||
// Called onPlayerQuit
|
||||
public void updatePlaytime(UUID uuid, Long playtime) {
|
||||
getUsersTable()
|
||||
.insertOrUpdate(
|
||||
uuid.toString(),
|
||||
DataManager
|
||||
.getInstance()
|
||||
.getDBConfig()
|
||||
.getString("database-settings.serverId"),
|
||||
playtime
|
||||
);
|
||||
userPlaytimes.remove(uuid);
|
||||
}
|
||||
|
||||
// Given the serverId returns the playtime from that server
|
||||
public Long getPlayTimeForServer(UUID uuid, String server) {
|
||||
if (
|
||||
userPlaytimes.containsKey(uuid) &&
|
||||
userPlaytimes.get(uuid).containsKey(server)
|
||||
) {
|
||||
return userPlaytimes.get(uuid).get(server);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// %PlayTimes_total%
|
||||
public Long getTotalPlayTime(UUID uuid) {
|
||||
Long playtime = 0L;
|
||||
Map<String, Long> userPlaytimeMap = userPlaytimes.get(uuid);
|
||||
|
||||
if (userPlaytimeMap != null) {
|
||||
for (Long individualPlaytime : userPlaytimeMap.values()) {
|
||||
playtime += individualPlaytime;
|
||||
}
|
||||
}
|
||||
|
||||
return playtime;
|
||||
}
|
||||
|
||||
public void purgeOldPlaytimeData() {
|
||||
Bukkit
|
||||
.getLogger()
|
||||
.info("[PlayTimes] Initiating purge of outdated playtime data...");
|
||||
|
||||
String serverId = DataManager
|
||||
.getInstance()
|
||||
.getDBConfig()
|
||||
.getString("database-settings.serverId");
|
||||
int months = DataManager
|
||||
.getInstance()
|
||||
.getDBConfig()
|
||||
.getInt("purge-database.months", 12);
|
||||
|
||||
Bukkit
|
||||
.getLogger()
|
||||
.info(
|
||||
String.format(
|
||||
"[PlayTimes] Purging playtime data for server ID '%s' that is older than %d months.",
|
||||
serverId,
|
||||
months
|
||||
)
|
||||
);
|
||||
this.usersTable.purgeOldPlaytimes(serverId, months);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
package me.codedred.playtimes.data.database.table;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import me.codedred.playtimes.data.database.datasource.DataSource;
|
||||
import me.codedred.playtimes.utils.Async;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
public class UsersTable {
|
||||
|
||||
private static final String TABLE_NAME = "playtimes";
|
||||
private final DataSource dataSource;
|
||||
|
||||
public UsersTable(DataSource dataSource) {
|
||||
this.dataSource = dataSource;
|
||||
}
|
||||
|
||||
public void createTable() {
|
||||
String createTableSql = String.format(
|
||||
"CREATE TABLE IF NOT EXISTS `%s` (" +
|
||||
"`uniqueId` VARCHAR(36) NOT NULL," +
|
||||
"`serverId` VARCHAR(255) NOT NULL," +
|
||||
"`playtime` BIGINT NOT NULL DEFAULT 0," +
|
||||
"`lastUpdated` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP," +
|
||||
"PRIMARY KEY (`uniqueId`, `serverId`))",
|
||||
TABLE_NAME
|
||||
);
|
||||
|
||||
try (
|
||||
Connection conn = dataSource.getConnection();
|
||||
PreparedStatement preparedStatement = conn.prepareStatement(
|
||||
createTableSql
|
||||
)
|
||||
) {
|
||||
preparedStatement.executeUpdate();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void insertOrUpdate(String uuid, String serverId, long playtime) {
|
||||
Async.run(() -> {
|
||||
String query = String.format(
|
||||
"INSERT INTO `%s` (`uniqueId`, `serverId`, `playtime`) VALUES (?, ?, ?) " +
|
||||
"ON DUPLICATE KEY UPDATE `playtime` = ?",
|
||||
TABLE_NAME
|
||||
);
|
||||
|
||||
try (
|
||||
Connection conn = dataSource.getConnection();
|
||||
PreparedStatement preparedStatement = conn.prepareStatement(query)
|
||||
) {
|
||||
preparedStatement.setString(1, uuid);
|
||||
preparedStatement.setString(2, serverId);
|
||||
preparedStatement.setLong(3, playtime);
|
||||
preparedStatement.setLong(4, playtime);
|
||||
|
||||
preparedStatement.executeUpdate();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public Map<String, Long> getPlaytimesByUuid(UUID uuid) {
|
||||
Map<String, Long> playtimes = new HashMap<>();
|
||||
|
||||
try (
|
||||
Connection conn = dataSource.getConnection();
|
||||
PreparedStatement preparedStatement = conn.prepareStatement(
|
||||
String.format("SELECT * FROM `%s` WHERE `uniqueId` = ?", TABLE_NAME)
|
||||
)
|
||||
) {
|
||||
preparedStatement.setString(1, uuid.toString());
|
||||
|
||||
try (ResultSet resultSet = preparedStatement.executeQuery()) {
|
||||
while (resultSet.next()) {
|
||||
String serverId = resultSet.getString("serverId");
|
||||
long playtime = resultSet.getLong("playtime");
|
||||
playtimes.put(serverId, playtime);
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return playtimes;
|
||||
}
|
||||
|
||||
public Map<String, Timestamp> getLastUpdatedTimesByUuid(UUID uuid) {
|
||||
Map<String, Timestamp> lastUpdatedTimes = new HashMap<>();
|
||||
|
||||
String query = String.format(
|
||||
"SELECT `serverId`, `lastUpdated` FROM `%s` WHERE `uniqueId` = ?",
|
||||
TABLE_NAME
|
||||
);
|
||||
try (
|
||||
Connection conn = dataSource.getConnection();
|
||||
PreparedStatement preparedStatement = conn.prepareStatement(query)
|
||||
) {
|
||||
preparedStatement.setString(1, uuid.toString());
|
||||
|
||||
try (ResultSet resultSet = preparedStatement.executeQuery()) {
|
||||
while (resultSet.next()) {
|
||||
String serverId = resultSet.getString("serverId");
|
||||
Timestamp lastUpdated = resultSet.getTimestamp("lastUpdated");
|
||||
lastUpdatedTimes.put(serverId, lastUpdated);
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return lastUpdatedTimes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes rows from the database where the last update was more than the specified number of months ago.
|
||||
*
|
||||
* @param serverId The server ID to match rows.
|
||||
* @param months The number of months to check for old data.
|
||||
*/
|
||||
public void purgeOldPlaytimes(String serverId, int months) {
|
||||
Async.run(() -> {
|
||||
String query = String.format(
|
||||
"DELETE FROM `%s` WHERE `serverId` = ? AND `lastUpdated` < (NOW() - INTERVAL ? MONTH)",
|
||||
TABLE_NAME
|
||||
);
|
||||
|
||||
try (
|
||||
Connection conn = dataSource.getConnection();
|
||||
PreparedStatement preparedStatement = conn.prepareStatement(query)
|
||||
) {
|
||||
preparedStatement.setString(1, serverId);
|
||||
preparedStatement.setInt(2, months);
|
||||
|
||||
int deletedRows = preparedStatement.executeUpdate();
|
||||
Bukkit
|
||||
.getLogger()
|
||||
.info(
|
||||
"[PlayTimes] Deleted " +
|
||||
deletedRows +
|
||||
" rows for serverId " +
|
||||
serverId +
|
||||
" older than " +
|
||||
months +
|
||||
" months."
|
||||
);
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,37 +1,68 @@
|
||||
package me.codedred.playtimes.listeners;
|
||||
|
||||
import java.util.UUID;
|
||||
import me.codedred.playtimes.PlayTimes;
|
||||
import me.codedred.playtimes.data.DataManager;
|
||||
import me.codedred.playtimes.data.database.manager.DatabaseManager;
|
||||
import me.codedred.playtimes.statistics.StatManager;
|
||||
import me.codedred.playtimes.statistics.StatisticType;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class Join implements Listener {
|
||||
|
||||
@EventHandler
|
||||
public void onJoin(PlayerJoinEvent event) {
|
||||
DataManager data = DataManager.getInstance();
|
||||
if (data.getData().contains("blocked." + event.getPlayer().getName().toLowerCase())) {
|
||||
return;
|
||||
}
|
||||
@EventHandler
|
||||
public void onJoin(PlayerJoinEvent event) {
|
||||
UUID uuid = event.getPlayer().getUniqueId();
|
||||
DataManager data = DataManager.getInstance();
|
||||
|
||||
UUID uuid = event.getPlayer().getUniqueId();
|
||||
ConfigurationSection leaderboardSection = data.getData().getConfigurationSection("leaderboard");
|
||||
// Database
|
||||
if (data.getDBConfig().getBoolean("database-settings.enabled")) {
|
||||
DatabaseManager dbManager = DatabaseManager.getInstance();
|
||||
dbManager.retrievePlayTime(uuid);
|
||||
|
||||
if (leaderboardSection == null) {
|
||||
leaderboardSection = data.getData().createSection("leaderboard");
|
||||
}
|
||||
// hacky bug fix that will update data again if database query was too slow.
|
||||
// this bug only arises when switching servers super fast!
|
||||
Bukkit
|
||||
.getScheduler()
|
||||
.runTaskLaterAsynchronously(
|
||||
PlayTimes.getPlugin(PlayTimes.class),
|
||||
() -> {
|
||||
dbManager.retrievePlayTime(uuid);
|
||||
},
|
||||
20L * 30
|
||||
);
|
||||
}
|
||||
|
||||
if (leaderboardSection.contains(uuid.toString())) {
|
||||
return;
|
||||
}
|
||||
// Leaderboard
|
||||
if (
|
||||
data
|
||||
.getData()
|
||||
.contains("blocked." + event.getPlayer().getName().toLowerCase())
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
long time = StatManager.getInstance().getPlayerStat(uuid, StatisticType.PLAYTIME);
|
||||
leaderboardSection.set(uuid.toString(), time);
|
||||
data.saveData();
|
||||
}
|
||||
ConfigurationSection leaderboardSection = data
|
||||
.getData()
|
||||
.getConfigurationSection("leaderboard");
|
||||
|
||||
if (leaderboardSection == null) {
|
||||
leaderboardSection = data.getData().createSection("leaderboard");
|
||||
}
|
||||
|
||||
if (leaderboardSection.contains(uuid.toString())) {
|
||||
return;
|
||||
}
|
||||
|
||||
long time = StatManager
|
||||
.getInstance()
|
||||
.getPlayerStat(uuid, StatisticType.PLAYTIME);
|
||||
leaderboardSection.set(uuid.toString(), time);
|
||||
|
||||
data.saveData();
|
||||
}
|
||||
}
|
||||
@@ -1,28 +1,46 @@
|
||||
package me.codedred.playtimes.listeners;
|
||||
|
||||
import java.util.UUID;
|
||||
import me.codedred.playtimes.data.DataManager;
|
||||
import me.codedred.playtimes.data.database.manager.DatabaseManager;
|
||||
import me.codedred.playtimes.statistics.StatManager;
|
||||
import me.codedred.playtimes.statistics.StatisticType;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class Quit implements Listener {
|
||||
|
||||
@EventHandler
|
||||
public void onQuit(PlayerQuitEvent event) {
|
||||
DataManager data = DataManager.getInstance();
|
||||
String playerName = event.getPlayer().getName().toLowerCase();
|
||||
if (data.getData().contains("blocked." + playerName)) {
|
||||
return;
|
||||
}
|
||||
@EventHandler
|
||||
public void onQuit(PlayerQuitEvent event) {
|
||||
UUID uuid = event.getPlayer().getUniqueId();
|
||||
DataManager data = DataManager.getInstance();
|
||||
|
||||
StatManager statManager = StatManager.getInstance();
|
||||
UUID uuid = event.getPlayer().getUniqueId();
|
||||
long playtime = statManager.getPlayerStat(uuid, StatisticType.PLAYTIME);
|
||||
data.getData().set("leaderboard." + uuid, playtime);
|
||||
data.saveData();
|
||||
}
|
||||
// Database
|
||||
if (data.getDBConfig().getBoolean("database-settings.enabled")) {
|
||||
DatabaseManager dbManager = DatabaseManager.getInstance();
|
||||
dbManager.updatePlaytime(
|
||||
uuid,
|
||||
StatManager
|
||||
.getInstance()
|
||||
.getPlayerStat(
|
||||
event.getPlayer().getUniqueId(),
|
||||
StatisticType.PLAYTIME
|
||||
) /
|
||||
20
|
||||
);
|
||||
}
|
||||
|
||||
// Leaderboard
|
||||
String playerName = event.getPlayer().getName().toLowerCase();
|
||||
if (data.getData().contains("blocked." + playerName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
StatManager statManager = StatManager.getInstance();
|
||||
long playtime = statManager.getPlayerStat(uuid, StatisticType.PLAYTIME);
|
||||
data.getData().set("leaderboard." + uuid, playtime);
|
||||
|
||||
data.saveData();
|
||||
}
|
||||
}
|
||||
@@ -1,79 +1,87 @@
|
||||
package me.codedred.playtimes.models;
|
||||
|
||||
import java.util.*;
|
||||
import me.codedred.playtimes.data.DataManager;
|
||||
import me.codedred.playtimes.statistics.StatManager;
|
||||
import me.codedred.playtimes.statistics.StatisticType;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class Leaderboard {
|
||||
|
||||
final String LEADERBOARD = "leaderboard";
|
||||
final String LEADERBOARD = "leaderboard";
|
||||
|
||||
/**
|
||||
* Grabs the uuids from the data file, sorts them, then removes redundant uuids and updates the top 10
|
||||
*
|
||||
* @return listing of top 10 players
|
||||
*/
|
||||
public Map<String, Integer> getTopTen() {
|
||||
Map<String, Integer> topTen = new LinkedHashMap<>();
|
||||
DataManager data = DataManager.getInstance();
|
||||
if (!data.getData().contains("leaderboard")) {
|
||||
return topTen;
|
||||
}
|
||||
for (String key : data.getData().getConfigurationSection(LEADERBOARD).getKeys(false)) {
|
||||
topTen.put(key, Integer.valueOf(data.getData().getString(LEADERBOARD + "." + key)));
|
||||
}
|
||||
/**
|
||||
* Grabs the uuids from the data file, sorts them, then removes redundant uuids and updates the top 10
|
||||
*
|
||||
* @return listing of top 10 players
|
||||
*/
|
||||
public Map<String, Integer> getTopTen() {
|
||||
Map<String, Integer> topTen = new LinkedHashMap<>();
|
||||
DataManager data = DataManager.getInstance();
|
||||
if (!data.getData().contains("leaderboard")) {
|
||||
return topTen;
|
||||
}
|
||||
for (String key : data
|
||||
.getData()
|
||||
.getConfigurationSection(LEADERBOARD)
|
||||
.getKeys(false)) {
|
||||
topTen.put(
|
||||
key,
|
||||
Integer.valueOf(data.getData().getString(LEADERBOARD + "." + key))
|
||||
);
|
||||
}
|
||||
|
||||
List<Map.Entry<String, Integer>> list = new LinkedList<>(topTen.entrySet());
|
||||
list.sort((o1, o2) -> o2.getValue() - o1.getValue());
|
||||
List<Map.Entry<String, Integer>> list = new LinkedList<>(topTen.entrySet());
|
||||
list.sort((o1, o2) -> o2.getValue() - o1.getValue());
|
||||
|
||||
if (list.size() > 20) {
|
||||
List<Map.Entry<String, Integer>> delList = list.subList(20, list.size());
|
||||
if (list.size() > 20) {
|
||||
List<Map.Entry<String, Integer>> delList = list.subList(20, list.size());
|
||||
|
||||
for (Map.Entry<String, Integer> key : delList) {
|
||||
data.getData().set(LEADERBOARD + "." + key.getKey(), null);
|
||||
}
|
||||
data.saveData();
|
||||
}
|
||||
for (Map.Entry<String, Integer> key : delList) {
|
||||
data.getData().set(LEADERBOARD + "." + key.getKey(), null);
|
||||
}
|
||||
data.saveData();
|
||||
}
|
||||
|
||||
if (list.size() > 9) {
|
||||
list = list.subList(0, 10);
|
||||
}
|
||||
if (list.size() > 9) {
|
||||
list = list.subList(0, 10);
|
||||
}
|
||||
|
||||
topTen.clear();
|
||||
topTen.clear();
|
||||
|
||||
for (Map.Entry<String, Integer> entry : list) {
|
||||
topTen.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
for (Map.Entry<String, Integer> entry : list) {
|
||||
topTen.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
updateTimes(topTen);
|
||||
return topTen;
|
||||
}
|
||||
updateTimes(topTen);
|
||||
return topTen;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the top ten times by querying the latest times from the StatManager and sorting the list.
|
||||
*
|
||||
* @param topTen the current leaderboard, with UUIDs and their corresponding time
|
||||
*/
|
||||
private void updateTimes(Map<String, Integer> topTen) {
|
||||
StatManager statManager = StatManager.getInstance();
|
||||
List<Map.Entry<String, Integer>> list = new ArrayList<>(topTen.entrySet());
|
||||
/**
|
||||
* Updates the top ten times by querying the latest times from the StatManager and sorting the list.
|
||||
*
|
||||
* @param topTen the current leaderboard, with UUIDs and their corresponding time
|
||||
*/
|
||||
private void updateTimes(Map<String, Integer> topTen) {
|
||||
StatManager statManager = StatManager.getInstance();
|
||||
List<Map.Entry<String, Integer>> list = new ArrayList<>(topTen.entrySet());
|
||||
|
||||
for (Map.Entry<String, Integer> entry : list) {
|
||||
String uuid = entry.getKey();
|
||||
int latestTime = (int) statManager.getPlayerStat(UUID.fromString(uuid), StatisticType.PLAYTIME);
|
||||
topTen.put(uuid, latestTime);
|
||||
}
|
||||
for (Map.Entry<String, Integer> entry : list) {
|
||||
String uuid = entry.getKey();
|
||||
int latestTime = (int) statManager.getPlayerStat(
|
||||
UUID.fromString(uuid),
|
||||
StatisticType.PLAYTIME
|
||||
);
|
||||
topTen.put(uuid, latestTime);
|
||||
}
|
||||
|
||||
list = new ArrayList<>(topTen.entrySet());
|
||||
list.sort(Map.Entry.<String, Integer>comparingByValue().reversed());
|
||||
list = new ArrayList<>(topTen.entrySet());
|
||||
list.sort(Map.Entry.<String, Integer>comparingByValue().reversed());
|
||||
|
||||
topTen.clear();
|
||||
topTen.clear();
|
||||
|
||||
for (int i = 0; i < Math.min(list.size(), 10); i++) {
|
||||
Map.Entry<String, Integer> entry = list.get(i);
|
||||
topTen.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < Math.min(list.size(), 10); i++) {
|
||||
Map.Entry<String, Integer> entry = list.get(i);
|
||||
topTen.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,10 @@
|
||||
package me.codedred.playtimes.player;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import me.codedred.playtimes.data.DataManager;
|
||||
import me.codedred.playtimes.data.database.manager.DatabaseManager;
|
||||
import me.codedred.playtimes.statistics.StatManager;
|
||||
import me.codedred.playtimes.statistics.StatisticType;
|
||||
import me.codedred.playtimes.time.TimeManager;
|
||||
@@ -10,61 +14,180 @@ import me.codedred.playtimes.utils.ServerUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class OfflinePlayer {
|
||||
|
||||
private final CommandSender sender;
|
||||
private final UUID target;
|
||||
private final String name;
|
||||
private final CommandSender sender;
|
||||
private final UUID target;
|
||||
private final String name;
|
||||
private List<String> message;
|
||||
|
||||
private List<String> message = new ArrayList<>();
|
||||
/**
|
||||
* Constructor for OfflinePlayer.
|
||||
* Initializes the message for the offline player.
|
||||
*
|
||||
* @param sender The command sender.
|
||||
* @param target The UUID of the offline player.
|
||||
* @param name The name of the offline player.
|
||||
*/
|
||||
public OfflinePlayer(CommandSender sender, UUID target, String name) {
|
||||
this.sender = sender;
|
||||
this.target = target;
|
||||
this.name = name;
|
||||
this.message = buildMessage();
|
||||
}
|
||||
|
||||
public OfflinePlayer(CommandSender sender, UUID target, String name) {
|
||||
this.target = target;
|
||||
this.sender = sender;
|
||||
this.name = name;
|
||||
buildMessage();
|
||||
/**
|
||||
* Builds the message to be sent to the sender about the offline player.
|
||||
* This involves fetching playtime statistics, formatting them,
|
||||
* and applying any necessary replacements and PlaceholderAPI placeholders.
|
||||
*
|
||||
* @return A list of formatted strings representing the message.
|
||||
*/
|
||||
private List<String> buildMessage() {
|
||||
DataManager dataManager = DataManager.getInstance();
|
||||
StatManager statManager = StatManager.getInstance();
|
||||
TimeManager timeManager = TimeManager.getInstance();
|
||||
|
||||
List<String> builtMessage = dataManager
|
||||
.getConfig()
|
||||
.getStringList("playtime.message");
|
||||
long rawTime = statManager.getPlayerStat(target, StatisticType.PLAYTIME);
|
||||
|
||||
if (ServerUtils.hasPAPI()) {
|
||||
builtMessage = applyPAPIPlaceholders(builtMessage);
|
||||
}
|
||||
|
||||
private void buildMessage() {
|
||||
DataManager dataManager = DataManager.getInstance();
|
||||
StatManager statManager = StatManager.getInstance();
|
||||
TimeManager timeManager = TimeManager.getInstance();
|
||||
return processMessageWithReplacements(
|
||||
builtMessage,
|
||||
prepareReplacements(rawTime, statManager, timeManager)
|
||||
);
|
||||
}
|
||||
|
||||
message = dataManager.getConfig().getStringList("playtime.message");
|
||||
/**
|
||||
* Applies PlaceholderAPI placeholders to the message if available.
|
||||
*
|
||||
* @param message The message list to process.
|
||||
* @return A list of messages with placeholders applied.
|
||||
*/
|
||||
private List<String> applyPAPIPlaceholders(List<String> message) {
|
||||
List<String> papiMessage = new ArrayList<>();
|
||||
for (String msg : message) {
|
||||
papiMessage.add(
|
||||
PAPIHolders.getHolders(Bukkit.getOfflinePlayer(target), msg)
|
||||
);
|
||||
}
|
||||
return papiMessage;
|
||||
}
|
||||
|
||||
long rawTime = statManager.getPlayerStat(target, StatisticType.PLAYTIME);
|
||||
/**
|
||||
* Prepares a map of replacements to be used in the message.
|
||||
*
|
||||
* @param rawTime The playtime statistic to format and include in the replacements.
|
||||
* @param statManager The StatManager instance to fetch additional statistics.
|
||||
* @param timeManager The TimeManager instance to format time.
|
||||
* @return A map of placeholder keys and their replacement values.
|
||||
*/
|
||||
private Map<String, String> prepareReplacements(
|
||||
long rawTime,
|
||||
StatManager statManager,
|
||||
TimeManager timeManager
|
||||
) {
|
||||
Map<String, String> replacements = new HashMap<>();
|
||||
replacements.put("%time%", timeManager.buildFormat(rawTime / 20));
|
||||
replacements.put("%player%", name);
|
||||
replacements.put(
|
||||
"%timesjoined%",
|
||||
Long.toString(
|
||||
statManager.getPlayerStat(target, StatisticType.TIMES_JOINED)
|
||||
)
|
||||
);
|
||||
replacements.put("%joindate%", statManager.getJoinDate(target));
|
||||
|
||||
if (ServerUtils.hasPAPI()) {
|
||||
List<String> papiMessage = new ArrayList<>();
|
||||
for (String msg : message) {
|
||||
papiMessage.add(PAPIHolders.getHolders(Bukkit.getOfflinePlayer(target), msg));
|
||||
}
|
||||
message = papiMessage;
|
||||
}
|
||||
|
||||
String timeFormat = timeManager.buildFormat(rawTime / 20);
|
||||
List<String> newMessage = new ArrayList<>();
|
||||
for (String msg : message) {
|
||||
msg = msg.replace("%time%", timeFormat);
|
||||
msg = msg.replace("%player%", name);
|
||||
msg = msg.replace("%timesjoined%", Long.toString(statManager.getPlayerStat(target, StatisticType.LEAVE)));
|
||||
msg = msg.replace("%joindate%", statManager.getJoinDate(target));
|
||||
newMessage.add(msg);
|
||||
}
|
||||
message = newMessage;
|
||||
if (
|
||||
DataManager
|
||||
.getInstance()
|
||||
.getDBConfig()
|
||||
.getBoolean("database-settings.enabled")
|
||||
) {
|
||||
replacements.put("%PlayTimes_db_serverId%", "DYNAMIC");
|
||||
replacements.put(
|
||||
"%PlayTimes_total%",
|
||||
timeManager.buildFormat(
|
||||
DatabaseManager.getInstance().getTotalPlayTime(target)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public void sendMessageToTarget() {
|
||||
for (String msg : message) {
|
||||
if (msg.contains("{\"text\":")) {
|
||||
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "tellraw " + sender + " " + ChatUtil.format(msg));
|
||||
} else {
|
||||
sender.sendMessage(ChatUtil.format(msg));
|
||||
}
|
||||
return replacements;
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the message by applying the necessary replacements.
|
||||
*
|
||||
* @param message The original message.
|
||||
* @param replacements The map of placeholders and their replacements.
|
||||
* @return A list of processed messages.
|
||||
*/
|
||||
private List<String> processMessageWithReplacements(
|
||||
List<String> message,
|
||||
Map<String, String> replacements
|
||||
) {
|
||||
List<String> newMessage = new ArrayList<>();
|
||||
boolean dbEnabled = DataManager
|
||||
.getInstance()
|
||||
.getDBConfig()
|
||||
.getBoolean("database-settings.enabled");
|
||||
TimeManager timeManager = TimeManager.getInstance();
|
||||
|
||||
for (String msg : message) {
|
||||
for (Map.Entry<String, String> entry : replacements.entrySet()) {
|
||||
if (entry.getKey().equals("%PlayTimes_db_serverId%") && dbEnabled) {
|
||||
// Handle dynamic replacement
|
||||
Pattern pattern = Pattern.compile("%PlayTimes_db_(\\w+)%");
|
||||
Matcher matcher = pattern.matcher(msg);
|
||||
StringBuffer sb = new StringBuffer();
|
||||
|
||||
while (matcher.find()) {
|
||||
String serverId = matcher.group(1);
|
||||
Long playTime = DatabaseManager
|
||||
.getInstance()
|
||||
.getPlayTimeForServer(target, serverId);
|
||||
matcher.appendReplacement(
|
||||
sb,
|
||||
playTime != null
|
||||
? timeManager.buildFormat(playTime)
|
||||
: timeManager.buildFormat(0)
|
||||
);
|
||||
}
|
||||
matcher.appendTail(sb);
|
||||
msg = sb.toString();
|
||||
} else {
|
||||
// Replace static placeholders
|
||||
msg = msg.replace(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
newMessage.add(msg);
|
||||
}
|
||||
|
||||
return newMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the formatted message to the sender.
|
||||
* This method determines the appropriate method to send the message
|
||||
* (e.g., standard chat message or JSON formatted tellraw command).
|
||||
*/
|
||||
public void sendMessageToTarget() {
|
||||
for (String msg : message) {
|
||||
String formattedMsg = ChatUtil.format(msg);
|
||||
if (formattedMsg.contains("{\"text\":")) {
|
||||
Bukkit.dispatchCommand(
|
||||
Bukkit.getConsoleSender(),
|
||||
"tellraw " + sender.getName() + " " + formattedMsg
|
||||
);
|
||||
} else {
|
||||
sender.sendMessage(formattedMsg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,10 @@
|
||||
package me.codedred.playtimes.player;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import me.codedred.playtimes.data.DataManager;
|
||||
import me.codedred.playtimes.data.database.manager.DatabaseManager;
|
||||
import me.codedred.playtimes.statistics.StatManager;
|
||||
import me.codedred.playtimes.statistics.StatisticType;
|
||||
import me.codedred.playtimes.time.TimeManager;
|
||||
@@ -10,90 +14,187 @@ import me.codedred.playtimes.utils.ServerUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class OnlinePlayer {
|
||||
|
||||
private final Player target;
|
||||
private final List<String> message;
|
||||
private final DataManager dataManager;
|
||||
private final StatManager statManager;
|
||||
private final Player target;
|
||||
private final List<String> message;
|
||||
private final DataManager dataManager;
|
||||
private final StatManager statManager;
|
||||
private final TimeManager timeManager;
|
||||
|
||||
private final TimeManager timeManager;
|
||||
/**
|
||||
* Constructor for OnlinePlayer.
|
||||
* Initializes the required managers and builds the message for the player.
|
||||
*
|
||||
* @param target The player for whom this OnlinePlayer instance is created.
|
||||
*/
|
||||
public OnlinePlayer(Player target) {
|
||||
this.target = target;
|
||||
this.dataManager = DataManager.getInstance();
|
||||
this.statManager = StatManager.getInstance();
|
||||
this.timeManager = TimeManager.getInstance();
|
||||
this.message = buildMessage();
|
||||
}
|
||||
|
||||
public OnlinePlayer(Player target) {
|
||||
this.target = target;
|
||||
this.message = new ArrayList<>();
|
||||
this.dataManager = DataManager.getInstance();
|
||||
this.statManager = StatManager.getInstance();
|
||||
this.timeManager = TimeManager.getInstance();
|
||||
buildMessage();
|
||||
/**
|
||||
* Builds the message to be sent to the player.
|
||||
* This involves fetching playtime statistics, formatting them,
|
||||
* and applying any necessary replacements and PlaceholderAPI placeholders.
|
||||
*
|
||||
* @return A list of formatted strings representing the message.
|
||||
*/
|
||||
private List<String> buildMessage() {
|
||||
List<String> builtMessage = new ArrayList<>();
|
||||
long rawTime = getPlaytimeStat();
|
||||
|
||||
builtMessage.addAll(
|
||||
dataManager.getConfig().getStringList("playtime.message")
|
||||
);
|
||||
|
||||
if (ServerUtils.hasPAPI()) {
|
||||
builtMessage = applyPAPIPlaceholders(builtMessage);
|
||||
}
|
||||
|
||||
private void buildMessage() {
|
||||
long rawTime;
|
||||
if (statManager.isLegacy()) {
|
||||
rawTime = statManager.getPlayerStat(target.getUniqueId(), StatisticType.PLAYTIME);
|
||||
} else {
|
||||
rawTime = statManager.getStats().getOnlineStatistic(target, StatisticType.PLAYTIME);
|
||||
}
|
||||
return processMessageWithReplacements(
|
||||
builtMessage,
|
||||
prepareReplacements(rawTime)
|
||||
);
|
||||
}
|
||||
|
||||
message.addAll(dataManager.getConfig().getStringList("playtime.message"));
|
||||
/**
|
||||
* Retrieves the playtime statistic for the player.
|
||||
*
|
||||
* @return The raw playtime statistic.
|
||||
*/
|
||||
private long getPlaytimeStat() {
|
||||
return statManager.isLegacy()
|
||||
? statManager.getPlayerStat(target.getUniqueId(), StatisticType.PLAYTIME)
|
||||
: statManager
|
||||
.getStats()
|
||||
.getOnlineStatistic(target, StatisticType.PLAYTIME);
|
||||
}
|
||||
|
||||
if (ServerUtils.hasPAPI()) {
|
||||
List<String> papiMessage = new ArrayList<>();
|
||||
for (String msg : message) {
|
||||
papiMessage.add(PAPIHolders.getHolders(target, msg));
|
||||
}
|
||||
message.clear();
|
||||
message.addAll(papiMessage);
|
||||
}
|
||||
/**
|
||||
* Applies PlaceholderAPI placeholders to the message if available.
|
||||
*
|
||||
* @param message The message list to process.
|
||||
* @return A list of messages with placeholders applied.
|
||||
*/
|
||||
private List<String> applyPAPIPlaceholders(List<String> message) {
|
||||
List<String> papiMessage = new ArrayList<>();
|
||||
for (String msg : message) {
|
||||
papiMessage.add(PAPIHolders.getHolders(target, msg));
|
||||
}
|
||||
return papiMessage;
|
||||
}
|
||||
|
||||
if (message.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* Prepares a map of replacements to be used in the message.
|
||||
*
|
||||
* @param rawTime The playtime statistic to format and include in the replacements.
|
||||
* @return A map of placeholder keys and their replacement values.
|
||||
*/
|
||||
private Map<String, String> prepareReplacements(long rawTime) {
|
||||
Map<String, String> replacements = new HashMap<>();
|
||||
replacements.put("%time%", timeManager.buildFormat(rawTime / 20));
|
||||
replacements.put("%player%", target.getName());
|
||||
replacements.put(
|
||||
"%timesjoined%",
|
||||
Long.toString(
|
||||
statManager.getPlayerStat(
|
||||
target.getUniqueId(),
|
||||
StatisticType.TIMES_JOINED
|
||||
)
|
||||
)
|
||||
);
|
||||
replacements.put(
|
||||
"%joindate%",
|
||||
statManager.getJoinDate(target.getUniqueId())
|
||||
);
|
||||
|
||||
Map<String, String> replacements = new HashMap<>();
|
||||
String timeFormat = timeManager.buildFormat(rawTime / 20);
|
||||
replacements.put("%time%", timeFormat);
|
||||
replacements.put("%player%", target.getName());
|
||||
replacements.put("%timesjoined%", Long.toString(statManager.getPlayerStat(target.getUniqueId(), StatisticType.LEAVE)));
|
||||
replacements.put("%joindate%", statManager.getJoinDate(target.getUniqueId()));
|
||||
|
||||
Pattern pattern = Pattern.compile("%(\\w+)%");
|
||||
List<String> newMessage = new ArrayList<>();
|
||||
for (String msg : message) {
|
||||
Matcher matcher = pattern.matcher(msg);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
while (matcher.find()) {
|
||||
String replacement = replacements.get(matcher.group(1));
|
||||
if (replacement != null) {
|
||||
matcher.appendReplacement(sb, replacement);
|
||||
}
|
||||
}
|
||||
matcher.appendTail(sb);
|
||||
newMessage.add(sb.toString());
|
||||
}
|
||||
message.clear();
|
||||
message.addAll(newMessage);
|
||||
if (
|
||||
DataManager
|
||||
.getInstance()
|
||||
.getDBConfig()
|
||||
.getBoolean("database-settings.enabled")
|
||||
) {
|
||||
replacements.put("%PlayTimes_db_serverId%", "DYNAMIC");
|
||||
replacements.put(
|
||||
"%PlayTimes_total%",
|
||||
timeManager.buildFormat(
|
||||
DatabaseManager.getInstance().getTotalPlayTime(target.getUniqueId())
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public void sendMessageToTarget() {
|
||||
String playerName = target.getName();
|
||||
for (String msg : message) {
|
||||
String formattedMsg = ChatUtil.format(msg)
|
||||
.replace("%time%", timeManager.buildFormat(StatManager.getInstance().getStats().getOnlineStatistic(target, StatisticType.PLAYTIME) / 20))
|
||||
.replace("%player%", playerName)
|
||||
.replace("%timesjoined%", Long.toString(StatManager.getInstance().getPlayerStat(target.getUniqueId(), StatisticType.LEAVE)))
|
||||
.replace("%joindate%", StatManager.getInstance().getJoinDate(target.getUniqueId()));
|
||||
return replacements;
|
||||
}
|
||||
|
||||
if (formattedMsg.contains("{\"text\":")) {
|
||||
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "tellraw " + target + " " + formattedMsg);
|
||||
} else {
|
||||
target.sendMessage(formattedMsg);
|
||||
}
|
||||
/**
|
||||
* Processes the message by applying the necessary replacements.
|
||||
*
|
||||
* @param message The original message.
|
||||
* @param replacements The map of placeholders and their replacements.
|
||||
* @return A list of processed messages.
|
||||
*/
|
||||
private List<String> processMessageWithReplacements(
|
||||
List<String> message,
|
||||
Map<String, String> replacements
|
||||
) {
|
||||
List<String> newMessage = new ArrayList<>();
|
||||
boolean dbEnabled = DataManager
|
||||
.getInstance()
|
||||
.getDBConfig()
|
||||
.getBoolean("database-settings.enabled");
|
||||
|
||||
for (String msg : message) {
|
||||
Matcher matcher = Pattern.compile("%PlayTimes_db_(\\w+)%").matcher(msg);
|
||||
StringBuffer sb = new StringBuffer();
|
||||
|
||||
while (matcher.find()) {
|
||||
if (dbEnabled) {
|
||||
String serverId = matcher.group(1);
|
||||
Long playTime = DatabaseManager
|
||||
.getInstance()
|
||||
.getPlayTimeForServer(target.getUniqueId(), serverId);
|
||||
matcher.appendReplacement(
|
||||
sb,
|
||||
playTime != null
|
||||
? timeManager.buildFormat(playTime)
|
||||
: timeManager.buildFormat(0)
|
||||
);
|
||||
}
|
||||
}
|
||||
matcher.appendTail(sb);
|
||||
msg = sb.toString();
|
||||
|
||||
// Replace other static placeholders
|
||||
for (Map.Entry<String, String> entry : replacements.entrySet()) {
|
||||
msg = msg.replace(entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
newMessage.add(msg);
|
||||
}
|
||||
}
|
||||
|
||||
return newMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the formatted message to the target player.
|
||||
* This method determines the appropriate method to send the message
|
||||
* (e.g., standard chat message or JSON formatted tellraw command).
|
||||
*/
|
||||
public void sendMessageToTarget() {
|
||||
for (String msg : message) {
|
||||
String formattedMsg = ChatUtil.format(msg);
|
||||
if (formattedMsg.contains("{\"text\":")) {
|
||||
Bukkit.dispatchCommand(
|
||||
Bukkit.getConsoleSender(),
|
||||
"tellraw " + target.getName() + " " + formattedMsg
|
||||
);
|
||||
} else {
|
||||
target.sendMessage(formattedMsg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,52 +1,54 @@
|
||||
package me.codedred.playtimes.server;
|
||||
|
||||
import me.codedred.playtimes.data.DataManager;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.UUID;
|
||||
import me.codedred.playtimes.data.DataManager;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
public class ServerManager {
|
||||
private static final ServerManager instance = new ServerManager();
|
||||
|
||||
public static ServerManager getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
private ServerStatus status;
|
||||
|
||||
public void register() {
|
||||
if (Bukkit.getOnlineMode())
|
||||
status = new ServerOnline();
|
||||
else
|
||||
status = new ServerOffline();
|
||||
cleanLeaderboard();
|
||||
}
|
||||
|
||||
public ServerStatus getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public UUID getUUID(String name) {
|
||||
return getStatus().getUUID(name);
|
||||
}
|
||||
|
||||
public String getName(UUID uuid) throws IOException {
|
||||
return getStatus().getName(uuid);
|
||||
}
|
||||
|
||||
public boolean isOnline() {
|
||||
return getStatus().isOnline();
|
||||
}
|
||||
|
||||
private void cleanLeaderboard() {
|
||||
DataManager data = DataManager.getInstance();
|
||||
if (!data.getData().contains("leaderboard"))
|
||||
return;
|
||||
for (String key : data.getData().getConfigurationSection("leaderboard").getKeys(false)) {
|
||||
if (Bukkit.getServer().getOfflinePlayer(UUID.fromString(key)).getName() == null)
|
||||
data.getData().set("leaderboard." + key, null);
|
||||
}
|
||||
data.saveData();
|
||||
private static final ServerManager instance = new ServerManager();
|
||||
|
||||
public static ServerManager getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
private ServerStatus status;
|
||||
|
||||
public void register() {
|
||||
if (Bukkit.getOnlineMode()) status = new ServerOnline(); else status =
|
||||
new ServerOffline();
|
||||
cleanLeaderboard();
|
||||
}
|
||||
|
||||
public ServerStatus getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public UUID getUUID(String name) {
|
||||
return getStatus().getUUID(name);
|
||||
}
|
||||
|
||||
public String getName(UUID uuid) throws IOException {
|
||||
return getStatus().getName(uuid);
|
||||
}
|
||||
|
||||
public boolean isOnline() {
|
||||
return getStatus().isOnline();
|
||||
}
|
||||
|
||||
private void cleanLeaderboard() {
|
||||
DataManager data = DataManager.getInstance();
|
||||
if (!data.getData().contains("leaderboard")) return;
|
||||
for (String key : data
|
||||
.getData()
|
||||
.getConfigurationSection("leaderboard")
|
||||
.getKeys(false)) {
|
||||
if (
|
||||
Bukkit.getServer().getOfflinePlayer(UUID.fromString(key)).getName() ==
|
||||
null
|
||||
) data.getData().set("leaderboard." + key, null);
|
||||
}
|
||||
data.saveData();
|
||||
}
|
||||
}
|
||||
@@ -2,8 +2,6 @@ package me.codedred.playtimes.server;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonObject;
|
||||
import me.codedred.playtimes.statistics.StatManager;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@@ -11,39 +9,54 @@ import java.io.InputStreamReader;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.UUID;
|
||||
import me.codedred.playtimes.statistics.StatManager;
|
||||
|
||||
public class ServerOffline implements ServerStatus {
|
||||
|
||||
@Override
|
||||
public UUID getUUID(String name) {
|
||||
try (InputStream is = new URL("https://api.mojang.com/users/profiles/minecraft/" + name).openStream()) {
|
||||
BufferedReader rd = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
|
||||
JsonObject rootobj = new Gson().fromJson(rd, JsonObject.class);
|
||||
String fixedName = rootobj.get("name").getAsString();
|
||||
UUID uuid = UUID.nameUUIDFromBytes(("OfflinePlayer:" + fixedName).getBytes(StandardCharsets.UTF_8));
|
||||
if (StatManager.getInstance().hasJoinedBefore(uuid)) {
|
||||
return null;
|
||||
}
|
||||
return uuid;
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
}
|
||||
@Override
|
||||
public UUID getUUID(String name) {
|
||||
try (
|
||||
InputStream is = new URL(
|
||||
"https://api.mojang.com/users/profiles/minecraft/" + name
|
||||
)
|
||||
.openStream()
|
||||
) {
|
||||
BufferedReader rd = new BufferedReader(
|
||||
new InputStreamReader(is, StandardCharsets.UTF_8)
|
||||
);
|
||||
JsonObject rootobj = new Gson().fromJson(rd, JsonObject.class);
|
||||
String fixedName = rootobj.get("name").getAsString();
|
||||
UUID uuid = UUID.nameUUIDFromBytes(
|
||||
("OfflinePlayer:" + fixedName).getBytes(StandardCharsets.UTF_8)
|
||||
);
|
||||
if (StatManager.getInstance().hasJoinedBefore(uuid)) {
|
||||
return null;
|
||||
}
|
||||
return uuid;
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOnline() {
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public boolean isOnline() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName(UUID uuid) throws IOException {
|
||||
try (InputStream is = new URL("https://mcapi.ca/player/profile/" + uuid).openStream();
|
||||
BufferedReader rd = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) {
|
||||
JsonObject rootobj = new Gson().fromJson(rd, JsonObject.class);
|
||||
return rootobj.get("name").getAsString();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return "User Not Found";
|
||||
}
|
||||
@Override
|
||||
public String getName(UUID uuid) throws IOException {
|
||||
try (
|
||||
InputStream is = new URL("https://mcapi.ca/player/profile/" + uuid)
|
||||
.openStream();
|
||||
BufferedReader rd = new BufferedReader(
|
||||
new InputStreamReader(is, StandardCharsets.UTF_8)
|
||||
)
|
||||
) {
|
||||
JsonObject rootobj = new Gson().fromJson(rd, JsonObject.class);
|
||||
return rootobj.get("name").getAsString();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return "User Not Found";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,8 +4,9 @@ import java.io.IOException;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface ServerStatus {
|
||||
public UUID getUUID(String name);
|
||||
|
||||
public UUID getUUID(String name);
|
||||
public boolean isOnline();
|
||||
public String getName(UUID uuid) throws IOException;
|
||||
public boolean isOnline();
|
||||
|
||||
public String getName(UUID uuid) throws IOException;
|
||||
}
|
||||
@@ -2,62 +2,62 @@ package me.codedred.playtimes.statistics;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonObject;
|
||||
import me.codedred.playtimes.data.DataManager;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.UUID;
|
||||
import me.codedred.playtimes.data.DataManager;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class LegacyStats implements Stats {
|
||||
|
||||
@Override
|
||||
public long getPlayerStatistic(UUID uuid, StatisticType type) {
|
||||
File playerStatistics = new File(worldFolder, uuid + ".json");
|
||||
@Override
|
||||
public long getPlayerStatistic(UUID uuid, StatisticType type) {
|
||||
File playerStatistics = new File(worldFolder, uuid + ".json");
|
||||
|
||||
if (playerStatistics.exists()) {
|
||||
try {
|
||||
JsonObject jsonObject = new Gson().fromJson(new FileReader(playerStatistics), JsonObject.class);
|
||||
if (playerStatistics.exists()) {
|
||||
try {
|
||||
JsonObject jsonObject = new Gson()
|
||||
.fromJson(new FileReader(playerStatistics), JsonObject.class);
|
||||
|
||||
return switch (type) {
|
||||
case PLAYTIME -> jsonObject.get("stat.playOneMinute").getAsLong();
|
||||
case LEAVE -> jsonObject.get("stat.leaveGame").getAsLong();
|
||||
case REST -> jsonObject.get("stat.timeSinceDeath").getAsLong();
|
||||
};
|
||||
|
||||
} catch (Exception e) {
|
||||
//e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return switch (type) {
|
||||
case PLAYTIME -> jsonObject.get("stat.playOneMinute").getAsLong();
|
||||
case TIMES_JOINED -> jsonObject.get("stat.leaveGame").getAsLong();
|
||||
};
|
||||
} catch (Exception e) {
|
||||
//e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getOnlineStatistic(Player player, StatisticType type) {
|
||||
return getPlayerStatistic(player.getUniqueId(), type);
|
||||
}
|
||||
@Override
|
||||
public long getOnlineStatistic(Player player, StatisticType type) {
|
||||
return getPlayerStatistic(player.getUniqueId(), type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasJoinedBefore(UUID uuid) {
|
||||
File playerStatistics = new File(worldFolder, uuid + ".json");
|
||||
return playerStatistics.exists();
|
||||
}
|
||||
@Override
|
||||
public boolean hasJoinedBefore(UUID uuid) {
|
||||
File playerStatistics = new File(worldFolder, uuid + ".json");
|
||||
return playerStatistics.exists();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getJoinDate(UUID uuid) {
|
||||
Player player = Bukkit.getPlayer(uuid);
|
||||
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DataManager.getInstance().getConfig().getString("date-format"));
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
if (player == null) {
|
||||
calendar.setTimeInMillis(Bukkit.getOfflinePlayer(uuid).getFirstPlayed());
|
||||
return simpleDateFormat.format(calendar.getTime());
|
||||
}
|
||||
else if (player.hasPlayedBefore()) {
|
||||
calendar.setTimeInMillis(player.getFirstPlayed());
|
||||
return simpleDateFormat.format(calendar.getTime());
|
||||
}
|
||||
return "Never Joined";
|
||||
@Override
|
||||
public String getJoinDate(UUID uuid) {
|
||||
Player player = Bukkit.getPlayer(uuid);
|
||||
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(
|
||||
DataManager.getInstance().getConfig().getString("date-format")
|
||||
);
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
if (player == null) {
|
||||
calendar.setTimeInMillis(Bukkit.getOfflinePlayer(uuid).getFirstPlayed());
|
||||
return simpleDateFormat.format(calendar.getTime());
|
||||
} else if (player.hasPlayedBefore()) {
|
||||
calendar.setTimeInMillis(player.getFirstPlayed());
|
||||
return simpleDateFormat.format(calendar.getTime());
|
||||
}
|
||||
return "Never Joined";
|
||||
}
|
||||
}
|
||||
@@ -2,81 +2,81 @@ package me.codedred.playtimes.statistics;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonObject;
|
||||
import me.codedred.playtimes.data.DataManager;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Statistic;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.UUID;
|
||||
import me.codedred.playtimes.data.DataManager;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Statistic;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class RisenStats implements Stats {
|
||||
|
||||
@Override
|
||||
public long getPlayerStatistic(UUID uuid, StatisticType type) {
|
||||
if (Bukkit.getPlayer(uuid) != null)
|
||||
return getOnlineStatistic(Bukkit.getPlayer(uuid), type);
|
||||
@Override
|
||||
public long getPlayerStatistic(UUID uuid, StatisticType type) {
|
||||
if (Bukkit.getPlayer(uuid) != null) return getOnlineStatistic(
|
||||
Bukkit.getPlayer(uuid),
|
||||
type
|
||||
);
|
||||
|
||||
File playerStatistics = new File(worldFolder, uuid + ".json");
|
||||
File playerStatistics = new File(worldFolder, uuid + ".json");
|
||||
|
||||
if (playerStatistics.exists()) {
|
||||
try {
|
||||
JsonObject jsonObject = new Gson().fromJson(new FileReader(playerStatistics), JsonObject.class);
|
||||
if (playerStatistics.exists()) {
|
||||
try {
|
||||
JsonObject jsonObject = new Gson()
|
||||
.fromJson(new FileReader(playerStatistics), JsonObject.class);
|
||||
|
||||
JsonObject pilot = (JsonObject) jsonObject.get("stats");
|
||||
JsonObject passenger = (JsonObject) pilot.get("minecraft:custom");
|
||||
JsonObject pilot = (JsonObject) jsonObject.get("stats");
|
||||
JsonObject passenger = (JsonObject) pilot.get("minecraft:custom");
|
||||
|
||||
switch (type) {
|
||||
case PLAYTIME -> {
|
||||
if (passenger.get("minecraft:play_time") == null)
|
||||
return passenger.get("minecraft:play_one_minute").getAsLong();
|
||||
return passenger.get("minecraft:play_time").getAsLong();
|
||||
}
|
||||
case LEAVE -> {
|
||||
return passenger.get("minecraft:leave_game").getAsLong();
|
||||
}
|
||||
case REST -> {
|
||||
return passenger.get("minecraft:time_since_rest").getAsLong();
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
//e.printStackTrace();
|
||||
}
|
||||
switch (type) {
|
||||
case PLAYTIME -> {
|
||||
if (passenger.get("minecraft:play_time") == null) return passenger
|
||||
.get("minecraft:play_one_minute")
|
||||
.getAsLong();
|
||||
return passenger.get("minecraft:play_time").getAsLong();
|
||||
}
|
||||
case TIMES_JOINED -> {
|
||||
return passenger.get("minecraft:leave_game").getAsLong();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
} catch (Exception e) {
|
||||
//e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getOnlineStatistic(Player player, StatisticType type) {
|
||||
return switch (type) {
|
||||
case PLAYTIME -> player.getStatistic(Statistic.PLAY_ONE_MINUTE);
|
||||
case REST -> player.getStatistic(Statistic.TIME_SINCE_REST);
|
||||
case LEAVE -> player.getStatistic(Statistic.LEAVE_GAME) + 1;
|
||||
};
|
||||
}
|
||||
@Override
|
||||
public long getOnlineStatistic(Player player, StatisticType type) {
|
||||
return switch (type) {
|
||||
case PLAYTIME -> player.getStatistic(Statistic.PLAY_ONE_MINUTE);
|
||||
case TIMES_JOINED -> player.getStatistic(Statistic.LEAVE_GAME) + 1;
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasJoinedBefore(UUID uuid) {
|
||||
File playerStatistics = new File(worldFolder, uuid + ".json");
|
||||
return playerStatistics.exists();
|
||||
}
|
||||
@Override
|
||||
public boolean hasJoinedBefore(UUID uuid) {
|
||||
File playerStatistics = new File(worldFolder, uuid + ".json");
|
||||
return playerStatistics.exists();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getJoinDate(UUID uuid) {
|
||||
Player player = Bukkit.getPlayer(uuid);
|
||||
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DataManager.getInstance().getConfig().getString("date-format"));
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
if (player == null) {
|
||||
calendar.setTimeInMillis(Bukkit.getOfflinePlayer(uuid).getFirstPlayed());
|
||||
return simpleDateFormat.format(calendar.getTime());
|
||||
}
|
||||
else if (player.hasPlayedBefore()) {
|
||||
calendar.setTimeInMillis(player.getFirstPlayed());
|
||||
return simpleDateFormat.format(calendar.getTime());
|
||||
}
|
||||
return "Never Joined";
|
||||
@Override
|
||||
public String getJoinDate(UUID uuid) {
|
||||
Player player = Bukkit.getPlayer(uuid);
|
||||
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(
|
||||
DataManager.getInstance().getConfig().getString("date-format")
|
||||
);
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
if (player == null) {
|
||||
calendar.setTimeInMillis(Bukkit.getOfflinePlayer(uuid).getFirstPlayed());
|
||||
return simpleDateFormat.format(calendar.getTime());
|
||||
} else if (player.hasPlayedBefore()) {
|
||||
calendar.setTimeInMillis(player.getFirstPlayed());
|
||||
return simpleDateFormat.format(calendar.getTime());
|
||||
}
|
||||
return "Never Joined";
|
||||
}
|
||||
}
|
||||
@@ -2,72 +2,77 @@ package me.codedred.playtimes.statistics;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonObject;
|
||||
import me.codedred.playtimes.data.DataManager;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Statistic;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.UUID;
|
||||
import me.codedred.playtimes.data.DataManager;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Statistic;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class RisingStats implements Stats {
|
||||
|
||||
@Override
|
||||
public long getPlayerStatistic(UUID uuid, StatisticType type) {
|
||||
if (Bukkit.getPlayer(uuid) != null)
|
||||
return getOnlineStatistic(Bukkit.getPlayer(uuid), type);
|
||||
File playerStatistics = new File(worldFolder, uuid + ".json");
|
||||
@Override
|
||||
public long getPlayerStatistic(UUID uuid, StatisticType type) {
|
||||
if (Bukkit.getPlayer(uuid) != null) return getOnlineStatistic(
|
||||
Bukkit.getPlayer(uuid),
|
||||
type
|
||||
);
|
||||
File playerStatistics = new File(worldFolder, uuid + ".json");
|
||||
|
||||
if (playerStatistics.exists()) {
|
||||
try {
|
||||
JsonObject jsonObject = new Gson().fromJson(new FileReader(playerStatistics), JsonObject.class);
|
||||
if (playerStatistics.exists()) {
|
||||
try {
|
||||
JsonObject jsonObject = new Gson()
|
||||
.fromJson(new FileReader(playerStatistics), JsonObject.class);
|
||||
|
||||
JsonObject pilot = (JsonObject) jsonObject.get("stats");
|
||||
JsonObject passenger = (JsonObject) pilot.get("minecraft:custom");
|
||||
JsonObject pilot = (JsonObject) jsonObject.get("stats");
|
||||
JsonObject passenger = (JsonObject) pilot.get("minecraft:custom");
|
||||
|
||||
return switch (type) {
|
||||
case PLAYTIME -> passenger.get("minecraft:play_one_minute").getAsLong();
|
||||
case LEAVE -> passenger.get("minecraft:leave_game").getAsLong();
|
||||
case REST -> passenger.get("minecraft:time_since_rest").getAsLong();
|
||||
};
|
||||
} catch (Exception e) {
|
||||
//e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getOnlineStatistic(Player player, StatisticType type) {
|
||||
return switch (type) {
|
||||
case PLAYTIME -> player.getStatistic(Statistic.PLAY_ONE_MINUTE);
|
||||
case REST -> player.getStatistic(Statistic.TIME_SINCE_REST);
|
||||
case LEAVE -> player.getStatistic(Statistic.LEAVE_GAME) + 1;
|
||||
case PLAYTIME -> passenger
|
||||
.get("minecraft:play_one_minute")
|
||||
.getAsLong();
|
||||
case TIMES_JOINED -> passenger
|
||||
.get("minecraft:leave_game")
|
||||
.getAsLong();
|
||||
};
|
||||
} catch (Exception e) {
|
||||
//e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasJoinedBefore(UUID uuid) {
|
||||
File playerStatistics = new File(worldFolder, uuid + ".json");
|
||||
return playerStatistics.exists();
|
||||
}
|
||||
@Override
|
||||
public long getOnlineStatistic(Player player, StatisticType type) {
|
||||
return switch (type) {
|
||||
case PLAYTIME -> player.getStatistic(Statistic.PLAY_ONE_MINUTE);
|
||||
case TIMES_JOINED -> player.getStatistic(Statistic.LEAVE_GAME) + 1;
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getJoinDate(UUID uuid) {
|
||||
Player player = Bukkit.getPlayer(uuid);
|
||||
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DataManager.getInstance().getConfig().getString("date-format"));
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
if (player == null) {
|
||||
calendar.setTimeInMillis(Bukkit.getOfflinePlayer(uuid).getFirstPlayed());
|
||||
return simpleDateFormat.format(calendar.getTime());
|
||||
}
|
||||
else if (player.hasPlayedBefore()) {
|
||||
calendar.setTimeInMillis(player.getFirstPlayed());
|
||||
return simpleDateFormat.format(calendar.getTime());
|
||||
}
|
||||
return "Never Joined";
|
||||
@Override
|
||||
public boolean hasJoinedBefore(UUID uuid) {
|
||||
File playerStatistics = new File(worldFolder, uuid + ".json");
|
||||
return playerStatistics.exists();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getJoinDate(UUID uuid) {
|
||||
Player player = Bukkit.getPlayer(uuid);
|
||||
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(
|
||||
DataManager.getInstance().getConfig().getString("date-format")
|
||||
);
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
if (player == null) {
|
||||
calendar.setTimeInMillis(Bukkit.getOfflinePlayer(uuid).getFirstPlayed());
|
||||
return simpleDateFormat.format(calendar.getTime());
|
||||
} else if (player.hasPlayedBefore()) {
|
||||
calendar.setTimeInMillis(player.getFirstPlayed());
|
||||
return simpleDateFormat.format(calendar.getTime());
|
||||
}
|
||||
return "Never Joined";
|
||||
}
|
||||
}
|
||||
@@ -1,67 +1,69 @@
|
||||
package me.codedred.playtimes.statistics;
|
||||
|
||||
import me.codedred.playtimes.time.TimeManager;
|
||||
import me.codedred.playtimes.utils.ServerUtils;
|
||||
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import me.codedred.playtimes.time.TimeManager;
|
||||
import me.codedred.playtimes.utils.ServerUtils;
|
||||
|
||||
public class StatManager {
|
||||
|
||||
private static final StatManager instance = new StatManager();
|
||||
private static final StatManager instance = new StatManager();
|
||||
|
||||
public static StatManager getInstance() {
|
||||
return instance;
|
||||
public static StatManager getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
private Stats stats;
|
||||
private boolean legacy = false;
|
||||
|
||||
public String name;
|
||||
|
||||
public void registerStatistics() {
|
||||
if (ServerUtils.isRisenVersion()) {
|
||||
stats = new RisenStats();
|
||||
name = "Risen";
|
||||
} else if (ServerUtils.isNewerVersion()) {
|
||||
stats = new RisingStats();
|
||||
name = "Rising";
|
||||
} else {
|
||||
stats = new LegacyStats();
|
||||
setLegacy();
|
||||
name = "Legacy";
|
||||
}
|
||||
}
|
||||
|
||||
private Stats stats;
|
||||
private boolean legacy = false;
|
||||
public Stats getStats() {
|
||||
return stats;
|
||||
}
|
||||
|
||||
public String name;
|
||||
public long getPlayerStat(UUID uuid, StatisticType type) {
|
||||
return getStats().getPlayerStatistic(uuid, type);
|
||||
}
|
||||
|
||||
public void registerStatistics() {
|
||||
if (ServerUtils.isRisenVersion()) {
|
||||
stats = new RisenStats();
|
||||
name = "Risen";
|
||||
}
|
||||
else if (ServerUtils.isNewerVersion()) {
|
||||
stats = new RisingStats();
|
||||
name = "Rising";
|
||||
}
|
||||
else {
|
||||
stats = new LegacyStats();
|
||||
setLegacy();
|
||||
name = "Legacy";
|
||||
}
|
||||
}
|
||||
public boolean hasJoinedBefore(UUID uuid) {
|
||||
return !getStats().hasJoinedBefore(uuid);
|
||||
}
|
||||
|
||||
public Stats getStats() {
|
||||
return stats;
|
||||
}
|
||||
public String getJoinDate(UUID uuid) {
|
||||
return getStats().getJoinDate(uuid);
|
||||
}
|
||||
|
||||
public long getPlayerStat(UUID uuid, StatisticType type) {
|
||||
return getStats().getPlayerStatistic(uuid, type);
|
||||
}
|
||||
private void setLegacy() {
|
||||
legacy = true;
|
||||
}
|
||||
|
||||
public boolean hasJoinedBefore(UUID uuid) {
|
||||
return !getStats().hasJoinedBefore(uuid);
|
||||
}
|
||||
|
||||
public String getJoinDate(UUID uuid) {
|
||||
return getStats().getJoinDate(uuid);
|
||||
}
|
||||
|
||||
private void setLegacy() {
|
||||
legacy = true;
|
||||
}
|
||||
|
||||
public boolean isLegacy() {
|
||||
return legacy;
|
||||
}
|
||||
|
||||
public String getUptime() {
|
||||
return TimeManager.getInstance().buildFormat((int) TimeUnit.MILLISECONDS.toSeconds(ManagementFactory.getRuntimeMXBean().getUptime()));
|
||||
}
|
||||
public boolean isLegacy() {
|
||||
return legacy;
|
||||
}
|
||||
|
||||
public String getUptime() {
|
||||
return TimeManager
|
||||
.getInstance()
|
||||
.buildFormat(
|
||||
(int) TimeUnit.MILLISECONDS.toSeconds(
|
||||
ManagementFactory.getRuntimeMXBean().getUptime()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,6 @@
|
||||
package me.codedred.playtimes.statistics;
|
||||
|
||||
public enum StatisticType {
|
||||
|
||||
// todo add monthly/weekly/daily times
|
||||
|
||||
PLAYTIME,
|
||||
LEAVE,
|
||||
REST
|
||||
|
||||
PLAYTIME,
|
||||
TIMES_JOINED,
|
||||
}
|
||||
@@ -1,17 +1,18 @@
|
||||
package me.codedred.playtimes.statistics;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.UUID;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public interface Stats {
|
||||
long getPlayerStatistic(UUID uuid, StatisticType type);
|
||||
boolean hasJoinedBefore(UUID uuid);
|
||||
String getJoinDate(UUID uuid);
|
||||
long getOnlineStatistic(Player player, StatisticType type);
|
||||
|
||||
long getPlayerStatistic(UUID uuid, StatisticType type);
|
||||
boolean hasJoinedBefore(UUID uuid);
|
||||
String getJoinDate(UUID uuid);
|
||||
long getOnlineStatistic(Player player, StatisticType type);
|
||||
|
||||
File worldFolder = new File(Bukkit.getServer().getWorlds().get(0).getWorldFolder(), "stats");
|
||||
File worldFolder = new File(
|
||||
Bukkit.getServer().getWorlds().get(0).getWorldFolder(),
|
||||
"stats"
|
||||
);
|
||||
}
|
||||
@@ -3,29 +3,60 @@ package me.codedred.playtimes.time;
|
||||
import me.codedred.playtimes.data.DataManager;
|
||||
|
||||
public class TimeConstants {
|
||||
private static String second, seconds, minute, minutes, hour, hours, day, days;
|
||||
|
||||
static {
|
||||
reload();
|
||||
}
|
||||
private static String second, seconds, minute, minutes, hour, hours, day, days;
|
||||
|
||||
public static void reload() {
|
||||
second = DataManager.getInstance().getConfig().getString("playtime.name.second");
|
||||
seconds = DataManager.getInstance().getConfig().getString("playtime.name.seconds");
|
||||
minute = DataManager.getInstance().getConfig().getString("playtime.name.minute");
|
||||
minutes = DataManager.getInstance().getConfig().getString("playtime.name.minutes");
|
||||
hour = DataManager.getInstance().getConfig().getString("playtime.name.hour");
|
||||
hours = DataManager.getInstance().getConfig().getString("playtime.name.hours");
|
||||
day = DataManager.getInstance().getConfig().getString("playtime.name.day");
|
||||
days = DataManager.getInstance().getConfig().getString("playtime.name.days");
|
||||
}
|
||||
static {
|
||||
reload();
|
||||
}
|
||||
|
||||
public static String getSecond() { return second; }
|
||||
public static String getSeconds() { return seconds; }
|
||||
public static String getMinute() { return minute; }
|
||||
public static String getMinutes() { return minutes; }
|
||||
public static String getHour() { return hour; }
|
||||
public static String getHours() { return hours; }
|
||||
public static String getDay() { return day; }
|
||||
public static String getDays() { return days; }
|
||||
public static void reload() {
|
||||
second =
|
||||
DataManager.getInstance().getConfig().getString("playtime.name.second");
|
||||
seconds =
|
||||
DataManager.getInstance().getConfig().getString("playtime.name.seconds");
|
||||
minute =
|
||||
DataManager.getInstance().getConfig().getString("playtime.name.minute");
|
||||
minutes =
|
||||
DataManager.getInstance().getConfig().getString("playtime.name.minutes");
|
||||
hour =
|
||||
DataManager.getInstance().getConfig().getString("playtime.name.hour");
|
||||
hours =
|
||||
DataManager.getInstance().getConfig().getString("playtime.name.hours");
|
||||
day = DataManager.getInstance().getConfig().getString("playtime.name.day");
|
||||
days =
|
||||
DataManager.getInstance().getConfig().getString("playtime.name.days");
|
||||
}
|
||||
|
||||
public static String getSecond() {
|
||||
return second;
|
||||
}
|
||||
|
||||
public static String getSeconds() {
|
||||
return seconds;
|
||||
}
|
||||
|
||||
public static String getMinute() {
|
||||
return minute;
|
||||
}
|
||||
|
||||
public static String getMinutes() {
|
||||
return minutes;
|
||||
}
|
||||
|
||||
public static String getHour() {
|
||||
return hour;
|
||||
}
|
||||
|
||||
public static String getHours() {
|
||||
return hours;
|
||||
}
|
||||
|
||||
public static String getDay() {
|
||||
return day;
|
||||
}
|
||||
|
||||
public static String getDays() {
|
||||
return days;
|
||||
}
|
||||
}
|
||||
@@ -5,43 +5,43 @@ import me.codedred.playtimes.time.formats.*;
|
||||
|
||||
public class TimeManager {
|
||||
|
||||
private static final TimeManager instance = new TimeManager();
|
||||
private static final TimeManager instance = new TimeManager();
|
||||
|
||||
public static TimeManager getInstance() {
|
||||
return instance;
|
||||
public static TimeManager getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
private Timings timings;
|
||||
|
||||
public void registerTimings() {
|
||||
DataManager data = DataManager.getInstance();
|
||||
|
||||
if (data.getConfig().getBoolean("playtime.only-hours")) {
|
||||
timings = new OnlyHours();
|
||||
return;
|
||||
}
|
||||
|
||||
private Timings timings;
|
||||
|
||||
public void registerTimings() {
|
||||
DataManager data = DataManager.getInstance();
|
||||
|
||||
if (data.getConfig().getBoolean("playtime.only-hours")) {
|
||||
timings = new OnlyHours();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!data.getConfig().getBoolean("playtime.show-seconds")) {
|
||||
if (!data.getConfig().getBoolean("playtime.show-days")) {
|
||||
timings = new NoDaysNoSeconds();
|
||||
return;
|
||||
}
|
||||
timings = new NoSeconds();
|
||||
return;
|
||||
}
|
||||
if (!data.getConfig().getBoolean("playtime.show-days")) {
|
||||
timings = new NoDays();
|
||||
return;
|
||||
}
|
||||
|
||||
timings = new NativeFormat();
|
||||
if (!data.getConfig().getBoolean("playtime.show-seconds")) {
|
||||
if (!data.getConfig().getBoolean("playtime.show-days")) {
|
||||
timings = new NoDaysNoSeconds();
|
||||
return;
|
||||
}
|
||||
timings = new NoSeconds();
|
||||
return;
|
||||
}
|
||||
if (!data.getConfig().getBoolean("playtime.show-days")) {
|
||||
timings = new NoDays();
|
||||
return;
|
||||
}
|
||||
|
||||
private Timings getTimings() {
|
||||
return timings;
|
||||
}
|
||||
timings = new NativeFormat();
|
||||
}
|
||||
|
||||
public String buildFormat(long time) {
|
||||
return getTimings().buildFormat(time);
|
||||
}
|
||||
private Timings getTimings() {
|
||||
return timings;
|
||||
}
|
||||
|
||||
public String buildFormat(long time) {
|
||||
return getTimings().buildFormat(time);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
package me.codedred.playtimes.time;
|
||||
|
||||
public interface Timings {
|
||||
|
||||
String buildFormat(long time);
|
||||
String buildFormat(long time);
|
||||
}
|
||||
@@ -5,62 +5,66 @@ import me.codedred.playtimes.time.Timings;
|
||||
|
||||
public class NativeFormat implements Timings {
|
||||
|
||||
@Override
|
||||
public String buildFormat(long time) {
|
||||
if (time < 60)
|
||||
return formatSeconds(time);
|
||||
@Override
|
||||
public String buildFormat(long time) {
|
||||
if (time < 60) return formatSeconds(time);
|
||||
|
||||
int minutes = (int) (time / 60);
|
||||
int secondsLeft = (int) (time % 60);
|
||||
int minutes = (int) (time / 60);
|
||||
int secondsLeft = (int) (time % 60);
|
||||
|
||||
// Time less than 1 hour
|
||||
if (minutes < 60)
|
||||
return formatMinutes(minutes, secondsLeft);
|
||||
// Time less than 1 hour
|
||||
if (minutes < 60) return formatMinutes(minutes, secondsLeft);
|
||||
|
||||
// Time less than 1 Day
|
||||
if (minutes < 1440) {
|
||||
int hours = minutes / 60;
|
||||
int minutesLeft = minutes % 60;
|
||||
return formatHours(hours, minutesLeft, secondsLeft);
|
||||
}
|
||||
|
||||
// Time greater than 1 day
|
||||
int days = minutes / 1440;
|
||||
int minutesLeft = minutes % 1440;
|
||||
return formatDays(days, minutesLeft, secondsLeft);
|
||||
// Time less than 1 Day
|
||||
if (minutes < 1440) {
|
||||
int hours = minutes / 60;
|
||||
int minutesLeft = minutes % 60;
|
||||
return formatHours(hours, minutesLeft, secondsLeft);
|
||||
}
|
||||
|
||||
private String formatSeconds(long seconds) {
|
||||
return seconds + (seconds == 1 ? TimeConstants.getSeconds() : TimeConstants.getSecond());
|
||||
}
|
||||
// Time greater than 1 day
|
||||
int days = minutes / 1440;
|
||||
int minutesLeft = minutes % 1440;
|
||||
return formatDays(days, minutesLeft, secondsLeft);
|
||||
}
|
||||
|
||||
private String formatMinutes(int minutes, int secondsLeft) {
|
||||
String format = minutes + (minutes == 1 ? TimeConstants.getMinute() : TimeConstants.getMinutes());
|
||||
if (secondsLeft > 0)
|
||||
format += formatSeconds(secondsLeft);
|
||||
return format;
|
||||
}
|
||||
private String formatSeconds(long seconds) {
|
||||
return (
|
||||
seconds +
|
||||
(seconds == 1 ? TimeConstants.getSeconds() : TimeConstants.getSecond())
|
||||
);
|
||||
}
|
||||
|
||||
private String formatHours(int hours, int minutesLeft, int secondsLeft) {
|
||||
String format = hours + (hours == 1 ? TimeConstants.getHour() : TimeConstants.getHours());
|
||||
if (minutesLeft >= 1)
|
||||
format += formatMinutes(minutesLeft, secondsLeft);
|
||||
else if (secondsLeft > 0)
|
||||
format += formatSeconds(secondsLeft);
|
||||
return format;
|
||||
}
|
||||
private String formatMinutes(int minutes, int secondsLeft) {
|
||||
String format =
|
||||
minutes +
|
||||
(minutes == 1 ? TimeConstants.getMinute() : TimeConstants.getMinutes());
|
||||
if (secondsLeft > 0) format += formatSeconds(secondsLeft);
|
||||
return format;
|
||||
}
|
||||
|
||||
private String formatDays(int days, int minutesLeft, int secondsLeft) {
|
||||
String format = days + (days == 1 ? TimeConstants.getDay() : TimeConstants.getDays());
|
||||
if (minutesLeft >= 60) {
|
||||
int hours = minutesLeft / 60;
|
||||
int minutesAfterHours = minutesLeft % 60;
|
||||
format += formatHours(hours, minutesAfterHours, secondsLeft);
|
||||
} else if (minutesLeft >= 1) {
|
||||
format += formatMinutes(minutesLeft, secondsLeft);
|
||||
} else if (secondsLeft > 0) {
|
||||
format += formatSeconds(secondsLeft);
|
||||
}
|
||||
return format;
|
||||
private String formatHours(int hours, int minutesLeft, int secondsLeft) {
|
||||
String format =
|
||||
hours + (hours == 1 ? TimeConstants.getHour() : TimeConstants.getHours());
|
||||
if (minutesLeft >= 1) format +=
|
||||
formatMinutes(minutesLeft, secondsLeft); else if (
|
||||
secondsLeft > 0
|
||||
) format += formatSeconds(secondsLeft);
|
||||
return format;
|
||||
}
|
||||
|
||||
private String formatDays(int days, int minutesLeft, int secondsLeft) {
|
||||
String format =
|
||||
days + (days == 1 ? TimeConstants.getDay() : TimeConstants.getDays());
|
||||
if (minutesLeft >= 60) {
|
||||
int hours = minutesLeft / 60;
|
||||
int minutesAfterHours = minutesLeft % 60;
|
||||
format += formatHours(hours, minutesAfterHours, secondsLeft);
|
||||
} else if (minutesLeft >= 1) {
|
||||
format += formatMinutes(minutesLeft, secondsLeft);
|
||||
} else if (secondsLeft > 0) {
|
||||
format += formatSeconds(secondsLeft);
|
||||
}
|
||||
return format;
|
||||
}
|
||||
}
|
||||
@@ -5,42 +5,45 @@ import me.codedred.playtimes.time.Timings;
|
||||
|
||||
public class NoDays implements Timings {
|
||||
|
||||
@Override
|
||||
public String buildFormat(long time) {
|
||||
if (time < 60)
|
||||
return formatSeconds(time);
|
||||
@Override
|
||||
public String buildFormat(long time) {
|
||||
if (time < 60) return formatSeconds(time);
|
||||
|
||||
int minutes = (int) (time / 60);
|
||||
int secondsLeft = (int) (time % 60);
|
||||
int minutes = (int) (time / 60);
|
||||
int secondsLeft = (int) (time % 60);
|
||||
|
||||
// Time less than 1 hour
|
||||
if (minutes < 60)
|
||||
return formatMinutes(minutes, secondsLeft);
|
||||
// Time less than 1 hour
|
||||
if (minutes < 60) return formatMinutes(minutes, secondsLeft);
|
||||
|
||||
// Greater than 1 hour, only in hours
|
||||
int hours = minutes / 60;
|
||||
int minutesLeft = minutes % 60;
|
||||
// Greater than 1 hour, only in hours
|
||||
int hours = minutes / 60;
|
||||
int minutesLeft = minutes % 60;
|
||||
|
||||
return formatHours(hours, minutesLeft, secondsLeft);
|
||||
}
|
||||
return formatHours(hours, minutesLeft, secondsLeft);
|
||||
}
|
||||
|
||||
private String formatSeconds(long seconds) {
|
||||
return seconds + (seconds == 1 ? TimeConstants.getSeconds() : TimeConstants.getSecond());
|
||||
}
|
||||
private String formatSeconds(long seconds) {
|
||||
return (
|
||||
seconds +
|
||||
(seconds == 1 ? TimeConstants.getSeconds() : TimeConstants.getSecond())
|
||||
);
|
||||
}
|
||||
|
||||
private String formatMinutes(int minutes, int secondsLeft) {
|
||||
String format = minutes + (minutes == 1 ? TimeConstants.getMinute() : TimeConstants.getMinutes());
|
||||
if (secondsLeft > 0)
|
||||
format += formatSeconds(secondsLeft);
|
||||
return format;
|
||||
}
|
||||
private String formatMinutes(int minutes, int secondsLeft) {
|
||||
String format =
|
||||
minutes +
|
||||
(minutes == 1 ? TimeConstants.getMinute() : TimeConstants.getMinutes());
|
||||
if (secondsLeft > 0) format += formatSeconds(secondsLeft);
|
||||
return format;
|
||||
}
|
||||
|
||||
private String formatHours(int hours, int minutesLeft, int secondsLeft) {
|
||||
String format = hours + (hours == 1 ? TimeConstants.getHour() : TimeConstants.getHours());
|
||||
if (minutesLeft >= 1)
|
||||
format += formatMinutes(minutesLeft, secondsLeft);
|
||||
else if (secondsLeft > 0)
|
||||
format += formatSeconds(secondsLeft);
|
||||
return format;
|
||||
}
|
||||
private String formatHours(int hours, int minutesLeft, int secondsLeft) {
|
||||
String format =
|
||||
hours + (hours == 1 ? TimeConstants.getHour() : TimeConstants.getHours());
|
||||
if (minutesLeft >= 1) format +=
|
||||
formatMinutes(minutesLeft, secondsLeft); else if (
|
||||
secondsLeft > 0
|
||||
) format += formatSeconds(secondsLeft);
|
||||
return format;
|
||||
}
|
||||
}
|
||||
@@ -5,29 +5,34 @@ import me.codedred.playtimes.time.Timings;
|
||||
|
||||
public class NoDaysNoSeconds implements Timings {
|
||||
|
||||
@Override
|
||||
public String buildFormat(long time) {
|
||||
if (time < 60)
|
||||
return time + ( time == 1 ? TimeConstants.getSeconds() : TimeConstants.getSecond());
|
||||
@Override
|
||||
public String buildFormat(long time) {
|
||||
if (time < 60) return (
|
||||
time +
|
||||
(time == 1 ? TimeConstants.getSeconds() : TimeConstants.getSecond())
|
||||
);
|
||||
|
||||
int minutes = (int) (time / 60);
|
||||
int minutes = (int) (time / 60);
|
||||
|
||||
// Time less than 1 hour
|
||||
if (minutes < 60)
|
||||
return minutes + (minutes == 1 ? TimeConstants.getMinute() : TimeConstants.getMinutes());
|
||||
// Time less than 1 hour
|
||||
if (minutes < 60) return (
|
||||
minutes +
|
||||
(minutes == 1 ? TimeConstants.getMinute() : TimeConstants.getMinutes())
|
||||
);
|
||||
|
||||
String format;
|
||||
String format;
|
||||
|
||||
int hours = minutes / 60;
|
||||
format = hours + (hours == 1 ? TimeConstants.getHour() : TimeConstants.getHours());
|
||||
int inMins = 60 * hours;
|
||||
int left = minutes - inMins;
|
||||
int hours = minutes / 60;
|
||||
format =
|
||||
hours + (hours == 1 ? TimeConstants.getHour() : TimeConstants.getHours());
|
||||
int inMins = 60 * hours;
|
||||
int left = minutes - inMins;
|
||||
|
||||
if (left >= 1)
|
||||
format = format + left + (left == 1 ? TimeConstants.getMinute() : TimeConstants.getMinutes());
|
||||
|
||||
return format;
|
||||
|
||||
}
|
||||
if (left >= 1) format =
|
||||
format +
|
||||
left +
|
||||
(left == 1 ? TimeConstants.getMinute() : TimeConstants.getMinutes());
|
||||
|
||||
return format;
|
||||
}
|
||||
}
|
||||
@@ -5,54 +5,59 @@ import me.codedred.playtimes.time.Timings;
|
||||
|
||||
public class NoSeconds implements Timings {
|
||||
|
||||
@Override
|
||||
public String buildFormat(long time) {
|
||||
if (time < 60)
|
||||
return formatSeconds(time);
|
||||
@Override
|
||||
public String buildFormat(long time) {
|
||||
if (time < 60) return formatSeconds(time);
|
||||
|
||||
int minutes = (int) (time / 60);
|
||||
int minutes = (int) (time / 60);
|
||||
|
||||
// Time less than 1 hour
|
||||
if (minutes < 60)
|
||||
return formatMinutes(minutes);
|
||||
// Time less than 1 hour
|
||||
if (minutes < 60) return formatMinutes(minutes);
|
||||
|
||||
// Time less than 1 Day
|
||||
if (minutes < 1440) {
|
||||
int hours = minutes / 60;
|
||||
int minutesLeft = minutes % 60;
|
||||
return formatHours(hours, minutesLeft);
|
||||
}
|
||||
|
||||
// Time greater than 1 day
|
||||
int days = minutes / 1440;
|
||||
int minutesLeft = minutes % 1440;
|
||||
return formatDays(days, minutesLeft);
|
||||
// Time less than 1 Day
|
||||
if (minutes < 1440) {
|
||||
int hours = minutes / 60;
|
||||
int minutesLeft = minutes % 60;
|
||||
return formatHours(hours, minutesLeft);
|
||||
}
|
||||
|
||||
private String formatSeconds(long seconds) {
|
||||
return seconds + (seconds == 1 ? TimeConstants.getSeconds() : TimeConstants.getSecond());
|
||||
}
|
||||
// Time greater than 1 day
|
||||
int days = minutes / 1440;
|
||||
int minutesLeft = minutes % 1440;
|
||||
return formatDays(days, minutesLeft);
|
||||
}
|
||||
|
||||
private String formatMinutes(int minutes) {
|
||||
return minutes + (minutes == 1 ? TimeConstants.getMinute() : TimeConstants.getMinutes());
|
||||
}
|
||||
private String formatSeconds(long seconds) {
|
||||
return (
|
||||
seconds +
|
||||
(seconds == 1 ? TimeConstants.getSeconds() : TimeConstants.getSecond())
|
||||
);
|
||||
}
|
||||
|
||||
private String formatHours(int hours, int minutesLeft) {
|
||||
String format = hours + (hours == 1 ? TimeConstants.getHour() : TimeConstants.getHours());
|
||||
if (minutesLeft >= 1)
|
||||
format += formatMinutes(minutesLeft);
|
||||
return format;
|
||||
}
|
||||
private String formatMinutes(int minutes) {
|
||||
return (
|
||||
minutes +
|
||||
(minutes == 1 ? TimeConstants.getMinute() : TimeConstants.getMinutes())
|
||||
);
|
||||
}
|
||||
|
||||
private String formatDays(int days, int minutesLeft) {
|
||||
String format = days + (days == 1 ? TimeConstants.getDay() : TimeConstants.getDays());
|
||||
if (minutesLeft >= 60) {
|
||||
int hours = minutesLeft / 60;
|
||||
int minutesAfterHours = minutesLeft % 60;
|
||||
format += formatHours(hours, minutesAfterHours);
|
||||
} else if (minutesLeft >= 1) {
|
||||
format += formatMinutes(minutesLeft);
|
||||
}
|
||||
return format;
|
||||
private String formatHours(int hours, int minutesLeft) {
|
||||
String format =
|
||||
hours + (hours == 1 ? TimeConstants.getHour() : TimeConstants.getHours());
|
||||
if (minutesLeft >= 1) format += formatMinutes(minutesLeft);
|
||||
return format;
|
||||
}
|
||||
|
||||
private String formatDays(int days, int minutesLeft) {
|
||||
String format =
|
||||
days + (days == 1 ? TimeConstants.getDay() : TimeConstants.getDays());
|
||||
if (minutesLeft >= 60) {
|
||||
int hours = minutesLeft / 60;
|
||||
int minutesAfterHours = minutesLeft % 60;
|
||||
format += formatHours(hours, minutesAfterHours);
|
||||
} else if (minutesLeft >= 1) {
|
||||
format += formatMinutes(minutesLeft);
|
||||
}
|
||||
return format;
|
||||
}
|
||||
}
|
||||
@@ -5,9 +5,10 @@ import me.codedred.playtimes.time.Timings;
|
||||
|
||||
public class OnlyHours implements Timings {
|
||||
|
||||
@Override
|
||||
public String buildFormat(long time) {
|
||||
return (Math.round((time/3600.0)*100d))/100d + TimeConstants.getHours();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String buildFormat(long time) {
|
||||
return (
|
||||
(Math.round((time / 3600.0) * 100d)) / 100d + TimeConstants.getHours()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package me.codedred.playtimes.utils;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.CompletionException;
|
||||
import java.util.concurrent.ForkJoinPool;
|
||||
import lombok.Getter;
|
||||
|
||||
public class Async {
|
||||
|
||||
@Getter
|
||||
private static final ForkJoinPool worker = new ForkJoinPool(
|
||||
8,
|
||||
ForkJoinPool.defaultForkJoinWorkerThreadFactory,
|
||||
(t, e) -> e.printStackTrace(),
|
||||
false
|
||||
);
|
||||
|
||||
public static CompletableFuture<Void> run(Runnable runnable) {
|
||||
return CompletableFuture.runAsync(
|
||||
() -> {
|
||||
try {
|
||||
runnable.run();
|
||||
} catch (Exception exception) {
|
||||
throw new CompletionException(exception);
|
||||
}
|
||||
},
|
||||
worker
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -6,37 +6,46 @@ import org.bukkit.command.CommandSender;
|
||||
|
||||
public class ChatUtil {
|
||||
|
||||
private static final DataManager DATA_MANAGER = DataManager.getInstance();
|
||||
private static final boolean IS_NEWER_VERSION = ServerUtils.isNewerVersion();
|
||||
private static final DataManager DATA_MANAGER = DataManager.getInstance();
|
||||
private static final boolean IS_NEWER_VERSION = ServerUtils.isNewerVersion();
|
||||
|
||||
public enum ChatTypes {
|
||||
NO_PERMISSION,
|
||||
PLAYER_NOT_FOUND,
|
||||
PLAYER_NEVER_PLAYED
|
||||
}
|
||||
public enum ChatTypes {
|
||||
NO_PERMISSION,
|
||||
PLAYER_NOT_FOUND,
|
||||
PLAYER_NEVER_PLAYED,
|
||||
}
|
||||
|
||||
public static void errno(CommandSender sender, ChatTypes type) {
|
||||
switch (type) {
|
||||
case NO_PERMISSION ->
|
||||
sender.sendMessage(format(DATA_MANAGER.getConfig().getString("messages.noPermission")));
|
||||
case PLAYER_NOT_FOUND ->
|
||||
sender.sendMessage(formatWithPrefix(DATA_MANAGER.getConfig().getString("messages.player-not-found")));
|
||||
case PLAYER_NEVER_PLAYED ->
|
||||
sender.sendMessage(formatWithPrefix(DATA_MANAGER.getConfig().getString("messages.player-never-joined")));
|
||||
}
|
||||
public static void errno(CommandSender sender, ChatTypes type) {
|
||||
switch (type) {
|
||||
case NO_PERMISSION -> sender.sendMessage(
|
||||
format(DATA_MANAGER.getConfig().getString("messages.noPermission"))
|
||||
);
|
||||
case PLAYER_NOT_FOUND -> sender.sendMessage(
|
||||
formatWithPrefix(
|
||||
DATA_MANAGER.getConfig().getString("messages.player-not-found")
|
||||
)
|
||||
);
|
||||
case PLAYER_NEVER_PLAYED -> sender.sendMessage(
|
||||
formatWithPrefix(
|
||||
DATA_MANAGER.getConfig().getString("messages.player-never-joined")
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public static String format(String msg) {
|
||||
msg = ChatColor.translateAlternateColorCodes('&', msg);
|
||||
if (IS_NEWER_VERSION)
|
||||
msg = HexUtil.hex(msg);
|
||||
return msg;
|
||||
}
|
||||
public static String format(String msg) {
|
||||
msg = ChatColor.translateAlternateColorCodes('&', msg);
|
||||
if (IS_NEWER_VERSION) msg = HexUtil.hex(msg);
|
||||
return msg;
|
||||
}
|
||||
|
||||
public static String formatWithPrefix(String msg) {
|
||||
msg = ChatColor.translateAlternateColorCodes('&', DATA_MANAGER.getConfig().getString("prefix") + " " + msg);
|
||||
if (IS_NEWER_VERSION)
|
||||
msg = HexUtil.hex(msg);
|
||||
return msg;
|
||||
}
|
||||
public static String formatWithPrefix(String msg) {
|
||||
msg =
|
||||
ChatColor.translateAlternateColorCodes(
|
||||
'&',
|
||||
DATA_MANAGER.getConfig().getString("prefix") + " " + msg
|
||||
);
|
||||
if (IS_NEWER_VERSION) msg = HexUtil.hex(msg);
|
||||
return msg;
|
||||
}
|
||||
}
|
||||
@@ -5,33 +5,31 @@ import java.util.UUID;
|
||||
|
||||
public class CoolDownUtil {
|
||||
|
||||
private CoolDownUtil() {
|
||||
throw new IllegalStateException("Utility Class");
|
||||
}
|
||||
private CoolDownUtil() {
|
||||
throw new IllegalStateException("Utility Class");
|
||||
}
|
||||
|
||||
private static final HashMap<UUID, Long> cooldowns = new HashMap<>();
|
||||
|
||||
public static void remove(UUID uuid) {
|
||||
cooldowns.remove(uuid);
|
||||
}
|
||||
|
||||
|
||||
public static void add(UUID uuid, long time) {
|
||||
cooldowns.put(uuid, time);
|
||||
}
|
||||
|
||||
|
||||
public static int left(UUID uuid) {
|
||||
return (int) (cooldowns.get(uuid)/1000 - (System.currentTimeMillis()/1000));
|
||||
}
|
||||
|
||||
|
||||
public static boolean contains(UUID uuid) {
|
||||
if (cooldowns.containsKey(uuid)) {
|
||||
if (cooldowns.get(uuid) > System.currentTimeMillis())
|
||||
return true;
|
||||
remove(uuid);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
private static final HashMap<UUID, Long> cooldowns = new HashMap<>();
|
||||
|
||||
public static void remove(UUID uuid) {
|
||||
cooldowns.remove(uuid);
|
||||
}
|
||||
|
||||
public static void add(UUID uuid, long time) {
|
||||
cooldowns.put(uuid, time);
|
||||
}
|
||||
|
||||
public static int left(UUID uuid) {
|
||||
return (int) (
|
||||
cooldowns.get(uuid) / 1000 - (System.currentTimeMillis() / 1000)
|
||||
);
|
||||
}
|
||||
|
||||
public static boolean contains(UUID uuid) {
|
||||
if (cooldowns.containsKey(uuid)) {
|
||||
if (cooldowns.get(uuid) > System.currentTimeMillis()) return true;
|
||||
remove(uuid);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -4,31 +4,31 @@ import net.md_5.bungee.api.ChatColor;
|
||||
|
||||
public class HexUtil {
|
||||
|
||||
private HexUtil() {
|
||||
throw new IllegalStateException("Utility Class");
|
||||
}
|
||||
private HexUtil() {
|
||||
throw new IllegalStateException("Utility Class");
|
||||
}
|
||||
|
||||
public static String hex(String message) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
int index = 0;
|
||||
public static String hex(String message) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
int index = 0;
|
||||
|
||||
while (index < message.length()) {
|
||||
int colorCodeStart = message.indexOf("<#", index);
|
||||
if (colorCodeStart != -1) {
|
||||
int colorCodeEnd = message.indexOf(">", colorCodeStart + 2);
|
||||
if (colorCodeEnd != -1) {
|
||||
builder.append(message, index, colorCodeStart);
|
||||
String hexCode = message.substring(colorCodeStart + 2, colorCodeEnd);
|
||||
ChatColor hexColor = ChatColor.of('#' + hexCode);
|
||||
builder.append(hexColor);
|
||||
index = colorCodeEnd + 1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
builder.append(message.substring(index));
|
||||
break;
|
||||
}
|
||||
while (index < message.length()) {
|
||||
int colorCodeStart = message.indexOf("<#", index);
|
||||
if (colorCodeStart != -1) {
|
||||
int colorCodeEnd = message.indexOf(">", colorCodeStart + 2);
|
||||
if (colorCodeEnd != -1) {
|
||||
builder.append(message, index, colorCodeStart);
|
||||
String hexCode = message.substring(colorCodeStart + 2, colorCodeEnd);
|
||||
ChatColor hexColor = ChatColor.of('#' + hexCode);
|
||||
builder.append(hexColor);
|
||||
index = colorCodeEnd + 1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
builder.append(message.substring(index));
|
||||
break;
|
||||
}
|
||||
|
||||
return ChatColor.translateAlternateColorCodes('&', builder.toString());
|
||||
}
|
||||
}
|
||||
return ChatColor.translateAlternateColorCodes('&', builder.toString());
|
||||
}
|
||||
}
|
||||
@@ -6,29 +6,29 @@ import org.bukkit.entity.Player;
|
||||
|
||||
public class PAPIHolders {
|
||||
|
||||
private PAPIHolders() {
|
||||
throw new IllegalStateException("Utility class");
|
||||
}
|
||||
private PAPIHolders() {
|
||||
throw new IllegalStateException("Utility class");
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates PAPI holders
|
||||
*
|
||||
* @param player the receiver of the message
|
||||
* @param msg the message that is being checked/translated
|
||||
* @return the fixed message with updated PAPI holders
|
||||
*/
|
||||
public static String getHolders(Player player, String msg) {
|
||||
return PlaceholderAPI.setPlaceholders(player, msg);
|
||||
}
|
||||
/**
|
||||
* Translates PAPI holders
|
||||
*
|
||||
* @param player the receiver of the message
|
||||
* @param msg the message that is being checked/translated
|
||||
* @return the fixed message with updated PAPI holders
|
||||
*/
|
||||
public static String getHolders(Player player, String msg) {
|
||||
return PlaceholderAPI.setPlaceholders(player, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates PAPI holders for offline players
|
||||
*
|
||||
* @param player the receiver of the message
|
||||
* @param msg the message that is being checked/translated
|
||||
* @return the fixed message with updated PAPI holders
|
||||
*/
|
||||
public static String getHolders(OfflinePlayer player, String msg) {
|
||||
return PlaceholderAPI.setPlaceholders(player, msg);
|
||||
}
|
||||
/**
|
||||
* Translates PAPI holders for offline players
|
||||
*
|
||||
* @param player the receiver of the message
|
||||
* @param msg the message that is being checked/translated
|
||||
* @return the fixed message with updated PAPI holders
|
||||
*/
|
||||
public static String getHolders(OfflinePlayer player, String msg) {
|
||||
return PlaceholderAPI.setPlaceholders(player, msg);
|
||||
}
|
||||
}
|
||||
@@ -1,48 +1,60 @@
|
||||
package me.codedred.playtimes.utils;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import me.codedred.playtimes.data.DataManager;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class ServerUtils {
|
||||
|
||||
private static Boolean isNewerVersion = null;
|
||||
private static Boolean isNewerVersion = null;
|
||||
|
||||
private ServerUtils() {
|
||||
throw new IllegalStateException("Utility Class");
|
||||
private ServerUtils() {
|
||||
throw new IllegalStateException("Utility Class");
|
||||
}
|
||||
|
||||
public static boolean isNewerVersion() {
|
||||
if (isNewerVersion == null) {
|
||||
try {
|
||||
Class<?> classMaterial = Material.class;
|
||||
Method method = classMaterial.getDeclaredMethod(
|
||||
"matchMaterial",
|
||||
String.class,
|
||||
boolean.class
|
||||
);
|
||||
isNewerVersion = (method != null);
|
||||
} catch (ReflectiveOperationException ex) {
|
||||
isNewerVersion = false;
|
||||
}
|
||||
}
|
||||
return isNewerVersion;
|
||||
}
|
||||
|
||||
public static boolean isNewerVersion() {
|
||||
if (isNewerVersion == null) {
|
||||
try {
|
||||
Class<?> classMaterial = Material.class;
|
||||
Method method = classMaterial.getDeclaredMethod("matchMaterial", String.class, boolean.class);
|
||||
isNewerVersion = (method != null);
|
||||
} catch (ReflectiveOperationException ex) {
|
||||
isNewerVersion = false;
|
||||
}
|
||||
}
|
||||
return isNewerVersion;
|
||||
}
|
||||
/**
|
||||
* Checks if the server version is 1.17+
|
||||
*
|
||||
* @return true if so
|
||||
*/
|
||||
public static boolean isRisenVersion() {
|
||||
String[] versionParts = Bukkit.getServer().getVersion().split("\\.");
|
||||
|
||||
/**
|
||||
* Checks if the server version is 1.17+
|
||||
*
|
||||
* @return true if so
|
||||
*/
|
||||
public static boolean isRisenVersion() {
|
||||
String[] versionParts = Bukkit.getServer().getVersion().split("\\.");
|
||||
int majorVersion = Integer.parseInt(versionParts[1]);
|
||||
int minorVersion = Integer.parseInt(versionParts[2].replaceAll("[^0-9]", ""));
|
||||
return majorVersion >= 17 && minorVersion >= 0;
|
||||
}
|
||||
int majorVersion = Integer.parseInt(
|
||||
versionParts[1].replaceAll("[^0-9]", "")
|
||||
);
|
||||
int minorVersion = 0;
|
||||
if (versionParts.length >= 3) minorVersion =
|
||||
Integer.parseInt(versionParts[2].replaceAll("[^0-9]", ""));
|
||||
|
||||
return majorVersion >= 17 && minorVersion >= 0;
|
||||
}
|
||||
|
||||
public static boolean hasPAPI() {
|
||||
if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null)
|
||||
return DataManager.getInstance().getConfig().getBoolean("use-papi-placeholders");
|
||||
return false;
|
||||
}
|
||||
public static boolean hasPAPI() {
|
||||
if (
|
||||
Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null
|
||||
) return DataManager
|
||||
.getInstance()
|
||||
.getConfig()
|
||||
.getBoolean("use-papi-placeholders");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,21 +1,21 @@
|
||||
# PlayTimes by CodedRed
|
||||
# For support please ask here: https://discord.gg/7A9UA2n
|
||||
# For support please ask here: https://github.com/CodedRed-Spigot/PlayTimes/issues
|
||||
|
||||
# Prefix will show before 'player-not-found' & 'player-never-joined' messages
|
||||
prefix: "&7[&b&lPlayTimes&7]"
|
||||
|
||||
|
||||
# Placeholders API info
|
||||
# Only enable this if you are using PAPI holders in PlayTimes
|
||||
# If you want to use PlayTimes placeholders in other plugins...
|
||||
# Just download PAPI and it will *automatically* register
|
||||
# Placeholders API info
|
||||
# Only enable this if you are using PAPI holders in PlayTimes
|
||||
# If you want to use PlayTimes placeholders in other plugins...
|
||||
# Just download PAPI and it will *automatically* register
|
||||
use-papi-placeholders: false
|
||||
|
||||
# PlayTimes format & message settings
|
||||
# The name refers to the format. See spigot plugin page for format examples
|
||||
# PlayTimes format & message settings
|
||||
# The name refers to the format. See spigot plugin page for format examples
|
||||
playtime:
|
||||
## Built-in Placeholders:
|
||||
## %player% %time% %timesjoined% %joindate%
|
||||
## Database placeholders info found here: https://github.com/CodedRed-Spigot/PlayTimes/wiki/Bungee-Support
|
||||
## You may also use PAPI Placeholders
|
||||
message:
|
||||
- "&b&m=======&b&l[%player%]&b&m======="
|
||||
@@ -47,10 +47,10 @@ uptime:
|
||||
- "&aServer Uptime:&f %serveruptime%"
|
||||
- "&b&m============================"
|
||||
|
||||
# /toppt command info
|
||||
## Built-in Placeholders:
|
||||
## %player% %place% %time% %joindate%
|
||||
## You may also use PAPI placeholders
|
||||
# /toppt command info
|
||||
## Built-in Placeholders:
|
||||
## %player% %place% %time% %joindate%
|
||||
## You may also use PAPI placeholders
|
||||
top-playtime:
|
||||
header: "&b******&9[&3&lPlayTime Leaderboards&9]&b*****"
|
||||
content: "&5%place%) &9&l%player% &9&o- %time%"
|
||||
@@ -58,10 +58,9 @@ top-playtime:
|
||||
enable-cooldown: true
|
||||
cooldown-seconds: 60
|
||||
|
||||
|
||||
# date-format can be changed to your liking.
|
||||
# For more placeholders look here: https://docs.oracle.com/javase/8/docs/api/java/text/SimpleDateFormat.html
|
||||
# This is the join date format.
|
||||
# date-format can be changed to your liking.
|
||||
# For more placeholders look here: https://docs.oracle.com/javase/8/docs/api/java/text/SimpleDateFormat.html
|
||||
# This is the join date format.
|
||||
date-format: "MM/dd/yyyy"
|
||||
|
||||
# Built in messages, may change to your liking :D
|
||||
@@ -70,3 +69,16 @@ messages:
|
||||
player-not-found: "&cPlayer not found."
|
||||
player-never-joined: "&cPlayer has never joined the server!"
|
||||
cooldown: "&cYou cannot use this command for %timeleft% seconds!"
|
||||
|
||||
# TODO: Decide if I will be added this or not:
|
||||
# This is an optional command for you to allow you to display more information.
|
||||
# permission: pt.more & pt.more.others
|
||||
playtime-more-command:
|
||||
enabled: false
|
||||
command: "more" # the actual command usage: /pt more
|
||||
message:
|
||||
- "&b&m=======&b&l[%player%'s Info']&b&m======="
|
||||
- "&aCreative PlayTime:&f %PlayTimes_db_creative%"
|
||||
- "&aSurvival PlayTime:&f %PlayTimes_db_survival%"
|
||||
- "&2Total:&f %PlayTimes_total%"
|
||||
- "&b&m============================"
|
||||
@@ -0,0 +1,21 @@
|
||||
database-settings:
|
||||
enabled: false
|
||||
type: "mysql" # change to 'sqlite' for SQLite
|
||||
database: "playtimes"
|
||||
host: "localhost"
|
||||
port: 3306
|
||||
user: "root"
|
||||
password: "password"
|
||||
useSSL: false
|
||||
# IMPORTANT:
|
||||
# 'serverId' must be UNIQUE to each server!
|
||||
# If you have multiple servers running PlayTimes, ensure each config has a unique 'serverId'.
|
||||
# The 'serverId' will also be used for placeholders, like %PlayTimes_db_serverId% (e.g., %PlayTimes_db_survival%).
|
||||
# The placeholder will return the playtime on that specific server.
|
||||
serverId: "survival"
|
||||
|
||||
# If enabled, upon starting your server it will purge all user info that is older than x months.
|
||||
# NOTE: This will only purge data for the specific 'serverId', not for all servers!
|
||||
purge-database:
|
||||
enabled: false
|
||||
months: 12
|
||||
@@ -3,7 +3,7 @@ main: me.codedred.playtimes.PlayTimes
|
||||
# Keeping 'Cmaaxx' as author for Metric purposes.
|
||||
author: Cmaaxx
|
||||
authors: [CodedRed]
|
||||
version: 1.5
|
||||
version: '${version}'
|
||||
softdepend: [PlaceholderAPI]
|
||||
|
||||
commands:
|
||||
|
||||
Reference in new issue
Block a user