28 Commits
Author SHA1 Message Date
CodedRed 5dc8a9c1a9 implement data purger 2023-11-25 19:54:01 -06:00
CodedRed 79c36751ca temp bug fix 2023-11-25 19:30:12 -06:00
CodedRed 7644a91756 bug fix 2023-11-25 19:12:42 -06:00
CodedRed 7abae06f54 various bug fixes 2023-11-25 18:47:48 -06:00
Christopher f58f182bc4 Update gradle.yml 2023-11-25 18:25:12 -06:00
CodedRed 7e7a16bcdf temp remove craftengine 2023-11-25 18:23:41 -06:00
Christopher 963ef56818 Create gradle.yml 2023-11-25 18:21:58 -06:00
CodedRed 9075dcd4ad ensure database is enabled 2023-11-25 18:18:31 -06:00
CodedRed 8300a4d2e3 add new placeholders to papi 2023-11-25 18:16:02 -06:00
CodedRed ab7178c3bb bump version 2023-11-25 18:15:50 -06:00
CodedRed 52d11b9958 implement total time placeholder 2023-11-25 18:09:59 -06:00
CodedRed dad538a890 config changes 2023-11-25 18:05:13 -06:00
CodedRed 30b43df049 format time placeholder 2023-11-25 17:54:55 -06:00
CodedRed 6e0043e197 proper stat grab 2023-11-25 17:51:57 -06:00
CodedRed 97cba3598a add timestamp field 2023-11-25 17:48:42 -06:00
CodedRed 32110fc2f2 database setting changes 2023-11-25 17:43:24 -06:00
CodedRed 8e5db3928f beta database build 2023-11-25 17:32:46 -06:00
CodedRed 1e7a5ffadb implemented dynamic placeholder 2023-11-25 16:36:22 -06:00
CodedRed 62a5966270 refactored offline/online player 2023-11-25 16:11:40 -06:00
CodedRed 47666f3a74 add db playtime to onJoin & onQuit 2023-11-25 15:42:05 -06:00
CodedRed 4ae41d91cb format 2023-11-25 15:34:55 -06:00
CodedRed ea39b43725 stat type refactor 2023-11-25 15:32:08 -06:00
CodedRed 7ab49c419d format 2023-11-25 15:28:25 -06:00
CodedRed ecea1640ab database refactoring 2023-11-25 15:24:07 -06:00
CodedRed cbc8253b4b [wip] db implementation 2023-11-22 17:35:04 -06:00
CodedRed e292e6e1b3 possible null exception bug fix 2023-11-22 14:53:16 -06:00
CodedRed fc8e2dc3c6 fixed update checker 2023-10-02 13:46:30 -05:00
CodedRed 1cbfe86785 1.5.3 Update
Changelog:
- Fixed plugin updater
- Fixed pt.others permission
- Implemented PAPI Placeholder: %PlayTimes_timesjoined%$
- Updated .gitignore
2023-10-02 13:23:08 -05:00
51 changed files with 3510 additions and 2291 deletions

No files matched your search

+22
View File
@@ -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
View File
@@ -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
+4 -3
View File
@@ -1,11 +1,10 @@
plugins {
id 'java'
id 'dev.codedred.craftengine' version '1.0.0'
}
group = 'dev.codedred'
version = '1.5.2'
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("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!");
}
});
}
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);
}
}
@@ -1,34 +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 me.codedred.playtimes.statistics.StatManager;
import java.util.UUID;
import org.bukkit.entity.Player;
public class TimelessPlayer
{
private final UUID uuid;
private final StatManager stats;
private final TimeManager timings;
public class TimelessPlayer {
public TimelessPlayer(final Player player) {
this.uuid = player.getUniqueId();
this.stats = StatManager.getInstance();
this.timings = TimeManager.getInstance();
}
private final UUID uuid;
private final StatManager stats;
private final TimeManager timings;
public TimelessPlayer(final UUID player) {
this.uuid = player;
this.stats = StatManager.getInstance();
this.timings = TimeManager.getInstance();
}
public TimelessPlayer(final Player player) {
this.uuid = player.getUniqueId();
this.stats = StatManager.getInstance();
this.timings = TimeManager.getInstance();
}
public String getPlayTime() {
return this.timings.buildFormat(this.stats.getPlayerStat(this.uuid, StatisticType.PLAYTIME) / 20L);
}
public TimelessPlayer(final UUID player) {
this.uuid = player;
this.stats = StatManager.getInstance();
this.timings = TimeManager.getInstance();
}
public long getRawPlayTimeInSeconds() {
return this.stats.getPlayerStat(this.uuid, StatisticType.PLAYTIME) / 20L;
}
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;
}
}
@@ -1,87 +1,90 @@
package me.codedred.playtimes.api;
import java.lang.management.ManagementFactory;
import java.util.concurrent.TimeUnit;
import me.codedred.playtimes.statistics.StatManager;
import java.util.Map;
import me.codedred.playtimes.models.Leaderboard;
import java.util.ArrayList;
import java.util.UUID;
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 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 Map<String, Integer> getTopMap() {
final Leaderboard board = new Leaderboard();
return board.getTopTen();
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 UUID getNumberOne() {
return this.getTop10Players().get(0);
}
public Map<String, Integer> getTopMap() {
final Leaderboard board = new Leaderboard();
return board.getTopTen();
}
public UUID getNumberTwo() {
return this.getTop10Players().get(1);
}
public UUID getNumberOne() {
return this.getTop10Players().get(0);
}
public UUID getNumberThree() {
return this.getTop10Players().get(2);
}
public UUID getNumberTwo() {
return this.getTop10Players().get(1);
}
public UUID getNumberFour() {
return this.getTop10Players().get(3);
}
public UUID getNumberThree() {
return this.getTop10Players().get(2);
}
public UUID getNumberFive() {
return this.getTop10Players().get(4);
}
public UUID getNumberFour() {
return this.getTop10Players().get(3);
}
public UUID getNumberSix() {
return this.getTop10Players().get(5);
}
public UUID getNumberFive() {
return this.getTop10Players().get(4);
}
public UUID getNumberSeven() {
return this.getTop10Players().get(6);
}
public UUID getNumberSix() {
return this.getTop10Players().get(5);
}
public UUID getNumberEight() {
return this.getTop10Players().get(7);
}
public UUID getNumberSeven() {
return this.getTop10Players().get(6);
}
public UUID getNumberNine() {
return this.getTop10Players().get(8);
}
public UUID getNumberEight() {
return this.getTop10Players().get(7);
}
public UUID getNumberTen() {
return this.getTop10Players().get(9);
}
public UUID getNumberNine() {
return this.getTop10Players().get(8);
}
public String getUptime() {
return StatManager.getInstance().getUptime();
}
public UUID getNumberTen() {
return this.getTop10Players().get(9);
}
public long getUptimeInSeconds() {
return TimeUnit.MILLISECONDS.toSeconds(ManagementFactory.getRuntimeMXBean().getUptime());
}
}
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,165 +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 (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) {
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,43 +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.time.LocalDateTime;
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);
ConfigurationSection leaderboardSection = data
.getData()
.getConfigurationSection("leaderboard");
// LocalDateTime now = LocalDateTime.now();
// String lastPlayed = now.toString();
// data.getData().set("last_played." + uuid, lastPlayed);
if (leaderboardSection == null) {
leaderboardSection = data.getData().createSection("leaderboard");
}
data.saveData();
}
if (leaderboardSection.contains(uuid.toString())) {
return;
}
long time = StatManager
.getInstance()
.getPlayerStat(uuid, StatisticType.PLAYTIME);
leaderboardSection.set(uuid.toString(), time);
data.saveData();
}
}
@@ -1,33 +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.time.LocalDateTime;
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);
// Database
if (data.getDBConfig().getBoolean("database-settings.enabled")) {
DatabaseManager dbManager = DatabaseManager.getInstance();
dbManager.updatePlaytime(
uuid,
StatManager
.getInstance()
.getPlayerStat(
event.getPlayer().getUniqueId(),
StatisticType.PLAYTIME
) /
20
);
}
// LocalDateTime now = LocalDateTime.now();
// String lastPlayed = now.toString();
// data.getData().set("last_played." + uuid, lastPlayed);
data.saveData();
}
// 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,53 +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].replaceAll("[^0-9]", "")
);
int minorVersion = 0;
if (versionParts.length >= 3) minorVersion =
Integer.parseInt(versionParts[2].replaceAll("[^0-9]", ""));
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;
}
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;
}
}
+28 -16
View File
@@ -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============================"
+21
View File
@@ -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
+1 -1
View File
@@ -3,7 +3,7 @@ main: me.codedred.playtimes.PlayTimes
# Keeping 'Cmaaxx' as author for Metric purposes.
author: Cmaaxx
authors: [CodedRed]
version: 1.5.2
version: '${version}'
softdepend: [PlaceholderAPI]
commands: