mirror of
https://github.com/CodedRed-Spigot/PlayTimes.git
synced 2026-11-06 01:32:33 -05:00
Compare commits
47
Commits
BETA
..
production
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
52e989b6b0 | ||
|
|
393000c8db | ||
|
|
0bfb51e9a1 | ||
|
|
d8ae3aca1e | ||
|
|
d8245aa23f | ||
|
|
cdead9f0f8 | ||
|
|
ff0670c65c | ||
|
|
deb86b6772 | ||
|
|
7ab32d73ab | ||
|
|
b3dfd53a37 | ||
|
|
ccc7e17383 | ||
|
|
53dbd2d991 | ||
|
|
1407e43c6f | ||
|
|
c45096360e | ||
|
|
9bae99ce8d | ||
|
|
e02e765154 | ||
|
|
a554819066 | ||
|
|
cc3e835b49 | ||
|
|
79a351fbfe | ||
|
|
5133c031d1 | ||
|
|
526feb0aa5 | ||
|
|
82493b27f6 | ||
|
|
c38bafb608 | ||
|
|
bab7c374f1 | ||
|
|
2ef20ea5d1 | ||
|
|
76c15ac56d | ||
|
|
19871bc0db | ||
|
|
e0747b37f7 | ||
|
|
7ac62d1681 | ||
|
|
e257740aaa | ||
|
|
7d0f7c76cd | ||
|
|
0e1f2146d6 | ||
|
|
02d75354df | ||
|
|
36b53c17cd | ||
|
|
534bbba9fc | ||
|
|
52800c3de0 | ||
|
|
4c1219de2b | ||
|
|
88a40062c9 | ||
|
|
931f192f95 | ||
|
|
6bc6e8395a | ||
|
|
4897fe11a8 | ||
|
|
c28ce839ea | ||
|
|
b38b080d4b | ||
|
|
c279d60d88 | ||
|
|
afe66090f9 | ||
|
|
cbc8b632e0 | ||
|
|
8630c14648 |
No files matched your search
+3
-1
@@ -5,6 +5,9 @@
|
||||
*.ipr
|
||||
*.iws
|
||||
|
||||
# Hide my todo txt file
|
||||
/src/main/resources/todo.txt
|
||||
|
||||
# IntelliJ
|
||||
out/
|
||||
# mpeltonen/sbt-idea plugin
|
||||
@@ -119,7 +122,6 @@ run/
|
||||
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
|
||||
!gradle-wrapper.jar
|
||||
|
||||
|
||||
# VS Code directories
|
||||
.vscode/
|
||||
|
||||
|
||||
+9
-22
@@ -2,38 +2,26 @@ plugins {
|
||||
id 'java'
|
||||
}
|
||||
|
||||
|
||||
group = 'dev.codedred'
|
||||
version = '1.5.4'
|
||||
|
||||
version = '1.6.2b'
|
||||
|
||||
repositories {
|
||||
mavenLocal()
|
||||
gradlePluginPortal()
|
||||
maven {
|
||||
name = 'spigotmc-repo'
|
||||
url = 'https://hub.spigotmc.org/nexus/content/repositories/snapshots/'
|
||||
}
|
||||
maven {
|
||||
name = 'sonatype'
|
||||
url = 'https://oss.sonatype.org/content/groups/public/'
|
||||
}
|
||||
maven {
|
||||
url = 'https://repo.extendedclip.com/content/repositories/placeholderapi/'
|
||||
}
|
||||
maven { name = 'spigotmc-repo'; url = 'https://hub.spigotmc.org/nexus/content/repositories/snapshots/' }
|
||||
maven { name = 'sonatype'; url = 'https://oss.sonatype.org/content/groups/public/' }
|
||||
maven { url = 'https://repo.extendedclip.com/content/repositories/placeholderapi/' }
|
||||
}
|
||||
|
||||
|
||||
dependencies {
|
||||
implementation 'org.jetbrains:annotations:23.0.0'
|
||||
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
|
||||
def targetJavaVersion = 8
|
||||
java {
|
||||
def javaVersion = JavaVersion.toVersion(targetJavaVersion)
|
||||
sourceCompatibility = javaVersion
|
||||
@@ -41,12 +29,11 @@ java {
|
||||
if (JavaVersion.current() < javaVersion) {
|
||||
toolchain.languageVersion = JavaLanguageVersion.of(targetJavaVersion)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType(JavaCompile).configureEach {
|
||||
if (targetJavaVersion >= 10 || JavaVersion.current().isJava10Compatible()) {
|
||||
options.release = targetJavaVersion
|
||||
}
|
||||
options.encoding = 'UTF-8'
|
||||
options.release = targetJavaVersion
|
||||
}
|
||||
|
||||
processResources {
|
||||
@@ -56,4 +43,4 @@ processResources {
|
||||
filesMatching('plugin.yml') {
|
||||
expand props
|
||||
}
|
||||
}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
#!/bin/bash
|
||||
|
||||
NEW_VERSION="1.6.2b"
|
||||
|
||||
git checkout main
|
||||
git pull origin main
|
||||
|
||||
git tag -a $NEW_VERSION -m "Release version $NEW_VERSION"
|
||||
|
||||
git push origin $NEW_VERSION
|
||||
|
||||
git checkout production
|
||||
git pull origin production
|
||||
|
||||
git merge main -m "Release $NEW_VERSION"
|
||||
|
||||
git push origin production
|
||||
|
||||
echo "Release $NEW_VERSION completed and merged into production."
|
||||
read -p "Press any key to continue... "
|
||||
@@ -2,6 +2,7 @@ package me.codedred.playtimes;
|
||||
|
||||
import java.util.*;
|
||||
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
||||
import me.codedred.playtimes.afk.AFKManager;
|
||||
import me.codedred.playtimes.data.DataManager;
|
||||
import me.codedred.playtimes.data.database.manager.DatabaseManager;
|
||||
import me.codedred.playtimes.models.Leaderboard;
|
||||
@@ -32,7 +33,7 @@ public class Expansions extends PlaceholderExpansion {
|
||||
|
||||
@Override
|
||||
public @NotNull String getVersion() {
|
||||
return "1.5.4";
|
||||
return "1.6.1";
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -56,29 +57,44 @@ public class Expansions extends PlaceholderExpansion {
|
||||
.getInstance()
|
||||
.getPlayerStat(player.getUniqueId(), StatisticType.TIMES_JOINED)
|
||||
);
|
||||
// New cases for %PlayTimes_db_serverId% and %PlayTimes_total%
|
||||
case "total":
|
||||
return getTotalPlaytime(player);
|
||||
case "rawtime":
|
||||
return getRawtime(player);
|
||||
case "afktime":
|
||||
return getAfktime(player);
|
||||
case "global_playtime":
|
||||
return getGlobalPlaytime(player);
|
||||
case "global_rawtime":
|
||||
return getGlobalRawtime(player);
|
||||
case "global_afktime":
|
||||
return getGlobalAfktime(player);
|
||||
default:
|
||||
if (identifier.startsWith("db_")) {
|
||||
return getServerSpecificPlaytime(player, identifier.substring(3));
|
||||
if (identifier.startsWith("rawtime_")) {
|
||||
return getServerSpecificRawtime(player, identifier.substring(8));
|
||||
}
|
||||
if (identifier.startsWith("playtime_")) {
|
||||
return getServerSpecificPlaytime(player, identifier.substring(9));
|
||||
}
|
||||
if (identifier.startsWith("afktime_")) {
|
||||
return getServerSpecificAfktime(player, identifier.substring(8));
|
||||
}
|
||||
return handleLeaderboardIdentifier(identifier);
|
||||
}
|
||||
}
|
||||
|
||||
private String getTotalPlaytime(OfflinePlayer player) {
|
||||
if (
|
||||
DataManager
|
||||
.getInstance()
|
||||
.getDBConfig()
|
||||
.getBoolean("database-settings.enabled")
|
||||
) {
|
||||
private String getServerSpecificRawtime(
|
||||
OfflinePlayer player,
|
||||
String serverId
|
||||
) {
|
||||
if (DataManager.getInstance().hasDatabase()) {
|
||||
TimeManager timeManager = TimeManager.getInstance();
|
||||
Long totalPlaytime = DatabaseManager
|
||||
.getInstance()
|
||||
.getTotalPlayTime(player.getUniqueId());
|
||||
return timeManager.buildFormat(totalPlaytime != null ? totalPlaytime : 0);
|
||||
DatabaseManager dbManager = DatabaseManager.getInstance();
|
||||
if (dbManager.hasTimeForServer(player.getUniqueId(), serverId)) {
|
||||
Long rawtime = dbManager
|
||||
.getTimeForServer(player.getUniqueId(), serverId)
|
||||
.get("playtime");
|
||||
return timeManager.buildFormat(rawtime != null ? rawtime : 0);
|
||||
}
|
||||
return timeManager.buildFormat(0);
|
||||
}
|
||||
return "N/A";
|
||||
}
|
||||
@@ -87,22 +103,89 @@ public class Expansions extends PlaceholderExpansion {
|
||||
OfflinePlayer player,
|
||||
String serverId
|
||||
) {
|
||||
if (
|
||||
DataManager
|
||||
.getInstance()
|
||||
.getDBConfig()
|
||||
.getBoolean("database-settings.enabled")
|
||||
) {
|
||||
if (DataManager.getInstance().hasDatabase()) {
|
||||
TimeManager timeManager = TimeManager.getInstance();
|
||||
Long playtime = DatabaseManager
|
||||
DatabaseManager dbManager = DatabaseManager.getInstance();
|
||||
if (dbManager.hasTimeForServer(player.getUniqueId(), serverId)) {
|
||||
Map<String, Long> timeForServer = dbManager.getTimeForServer(
|
||||
player.getUniqueId(),
|
||||
serverId
|
||||
);
|
||||
Long playtime =
|
||||
timeForServer.get("playtime") -
|
||||
timeForServer.getOrDefault("afktime", 0L);
|
||||
return timeManager.buildFormat(playtime != null ? playtime : 0);
|
||||
}
|
||||
return timeManager.buildFormat(0);
|
||||
}
|
||||
return "N/A";
|
||||
}
|
||||
|
||||
private String getServerSpecificAfktime(
|
||||
OfflinePlayer player,
|
||||
String serverId
|
||||
) {
|
||||
if (DataManager.getInstance().hasDatabase()) {
|
||||
TimeManager timeManager = TimeManager.getInstance();
|
||||
DatabaseManager dbManager = DatabaseManager.getInstance();
|
||||
if (dbManager.hasTimeForServer(player.getUniqueId(), serverId)) {
|
||||
Long afktime = dbManager
|
||||
.getTimeForServer(player.getUniqueId(), serverId)
|
||||
.get("afktime");
|
||||
return timeManager.buildFormat(afktime != null ? afktime : 0);
|
||||
}
|
||||
return timeManager.buildFormat(0);
|
||||
}
|
||||
return "N/A";
|
||||
}
|
||||
|
||||
private String getGlobalPlaytime(OfflinePlayer player) {
|
||||
if (DataManager.getInstance().hasDatabase()) {
|
||||
TimeManager timeManager = TimeManager.getInstance();
|
||||
Long globalPlaytime = DatabaseManager
|
||||
.getInstance()
|
||||
.getPlayTimeForServer(player.getUniqueId(), serverId);
|
||||
return timeManager.buildFormat(playtime != null ? playtime : 0);
|
||||
.getTotalPlaytime(player.getUniqueId());
|
||||
return timeManager.buildFormat(
|
||||
globalPlaytime != null ? globalPlaytime : 0
|
||||
);
|
||||
}
|
||||
return "N/A";
|
||||
}
|
||||
|
||||
private String getGlobalRawtime(OfflinePlayer player) {
|
||||
if (DataManager.getInstance().hasDatabase()) {
|
||||
TimeManager timeManager = TimeManager.getInstance();
|
||||
Long globalRawtime = DatabaseManager
|
||||
.getInstance()
|
||||
.getTotalRawtime(player.getUniqueId());
|
||||
return timeManager.buildFormat(globalRawtime != null ? globalRawtime : 0);
|
||||
}
|
||||
return "N/A";
|
||||
}
|
||||
|
||||
private String getGlobalAfktime(OfflinePlayer player) {
|
||||
if (DataManager.getInstance().hasDatabase()) {
|
||||
TimeManager timeManager = TimeManager.getInstance();
|
||||
Long globalAfktime = DatabaseManager
|
||||
.getInstance()
|
||||
.getTotalAfktime(player.getUniqueId());
|
||||
return timeManager.buildFormat(globalAfktime != null ? globalAfktime : 0);
|
||||
}
|
||||
return "N/A";
|
||||
}
|
||||
|
||||
private String getPlayerPlayTime(OfflinePlayer player) {
|
||||
StatManager stats = StatManager.getInstance();
|
||||
TimeManager timeManager = TimeManager.getInstance();
|
||||
long afkTime = AFKManager.getInstance().getAFKTime(player.getUniqueId());
|
||||
return timeManager.buildFormat(
|
||||
stats.getPlayerStat(player.getUniqueId(), StatisticType.PLAYTIME) /
|
||||
20 -
|
||||
afkTime
|
||||
);
|
||||
}
|
||||
|
||||
private String getRawtime(OfflinePlayer player) {
|
||||
StatManager stats = StatManager.getInstance();
|
||||
TimeManager timeManager = TimeManager.getInstance();
|
||||
return timeManager.buildFormat(
|
||||
@@ -110,6 +193,12 @@ public class Expansions extends PlaceholderExpansion {
|
||||
);
|
||||
}
|
||||
|
||||
private String getAfktime(OfflinePlayer player) {
|
||||
TimeManager timeManager = TimeManager.getInstance();
|
||||
long afkTime = AFKManager.getInstance().getAFKTime(player.getUniqueId());
|
||||
return timeManager.buildFormat(afkTime);
|
||||
}
|
||||
|
||||
private String handleLeaderboardIdentifier(String identifier) {
|
||||
if (identifier.contains("topname")) {
|
||||
return getLeaderboardPlayerName(identifier);
|
||||
|
||||
@@ -3,6 +3,11 @@ package me.codedred.playtimes;
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Objects;
|
||||
import me.codedred.playtimes.afk.AFKManager;
|
||||
import me.codedred.playtimes.afk.listeners.onChat;
|
||||
import me.codedred.playtimes.afk.listeners.onInteract;
|
||||
import me.codedred.playtimes.afk.listeners.onJoinQuit;
|
||||
import me.codedred.playtimes.afk.listeners.onMove;
|
||||
import me.codedred.playtimes.commands.Time;
|
||||
import me.codedred.playtimes.commands.TopTime;
|
||||
import me.codedred.playtimes.commands.Uptime;
|
||||
@@ -16,6 +21,7 @@ import me.codedred.playtimes.statistics.StatManager;
|
||||
import me.codedred.playtimes.time.TimeManager;
|
||||
import me.codedred.playtimes.utils.ChatUtil;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
@@ -24,8 +30,6 @@ public class PlayTimes extends JavaPlugin {
|
||||
@Override
|
||||
public void onEnable() {
|
||||
checkForUpdate();
|
||||
DataManager dataManager = DataManager.getInstance();
|
||||
dataManager.reloadAll();
|
||||
|
||||
ServerManager.getInstance().register();
|
||||
StatManager.getInstance().registerStatistics();
|
||||
@@ -44,18 +48,44 @@ public class PlayTimes extends JavaPlugin {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
Metrics metrics = new Metrics(this, 5289);
|
||||
|
||||
AFKManager.getInstance().startAFKChecker();
|
||||
getLogger().info("Successfully loaded.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
AFKManager.getInstance().endAFKChecker();
|
||||
getLogger().info("PlayTimes shutting down");
|
||||
}
|
||||
|
||||
private void registerEvents() {
|
||||
PluginManager pm = getServer().getPluginManager();
|
||||
DataManager data = DataManager.getInstance();
|
||||
|
||||
pm.registerEvents(new Join(), this);
|
||||
pm.registerEvents(new Quit(), this);
|
||||
|
||||
if (data.hasAfkEnabled()) {
|
||||
pm.registerEvents(new onJoinQuit(), this);
|
||||
|
||||
FileConfiguration config = data.getConfig();
|
||||
boolean cancelAfkOnMove = config.getBoolean(
|
||||
"afk-settings.cancel-afk.on-player-move"
|
||||
);
|
||||
boolean cancelAfkOnChat = config.getBoolean(
|
||||
"afk-settings.cancel-afk.on-player-chat"
|
||||
);
|
||||
boolean cancelAfkOnInteract = config.getBoolean(
|
||||
"afk-settings.cancel-afk.on-player-interact"
|
||||
);
|
||||
|
||||
if (cancelAfkOnMove || cancelAfkOnChat || cancelAfkOnInteract) {
|
||||
if (cancelAfkOnMove) pm.registerEvents(new onMove(), this);
|
||||
if (cancelAfkOnChat) pm.registerEvents(new onChat(), this);
|
||||
if (cancelAfkOnInteract) pm.registerEvents(new onInteract(), this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void registerCommands() {
|
||||
|
||||
@@ -31,9 +31,13 @@ public class UpdateChecker {
|
||||
connection.setReadTimeout(5000);
|
||||
connection.setUseCaches(true);
|
||||
|
||||
latestVersion =
|
||||
new BufferedReader(new InputStreamReader(connection.getInputStream()))
|
||||
.readLine();
|
||||
try (
|
||||
BufferedReader reader = new BufferedReader(
|
||||
new InputStreamReader(connection.getInputStream())
|
||||
)
|
||||
) {
|
||||
latestVersion = reader.readLine();
|
||||
}
|
||||
|
||||
if (latestVersion == null || latestVersion.isEmpty()) {
|
||||
throw new IOException("Failed to retrieve latest version.");
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
package me.codedred.playtimes.afk;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
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.utils.ChatUtil;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
|
||||
public class AFKManager {
|
||||
|
||||
private static AFKManager instance = null;
|
||||
|
||||
private final HashMap<UUID, Long> lastActive = new HashMap<>();
|
||||
private final HashMap<UUID, Long> afkTime = new HashMap<>();
|
||||
private final FileConfiguration config;
|
||||
private long afkThresholdMillis;
|
||||
|
||||
private boolean notifyOnAfk;
|
||||
private boolean notifyOnBack;
|
||||
|
||||
private String onAfkMessage;
|
||||
private String onBackMessage;
|
||||
|
||||
private BukkitTask afkCheckerTask = null;
|
||||
|
||||
private AFKManager() {
|
||||
config = DataManager.getInstance().getConfig();
|
||||
afkThresholdMillis = config.getLong("afk-settings.threshold") * 60L * 1000L;
|
||||
notifyOnAfk = config.getBoolean("afk-settings.broadcast-afk.on-enter-afk");
|
||||
notifyOnBack = config.getBoolean("afk-settings.broadcast-afk.on-exit-afk");
|
||||
onAfkMessage = config.getString("afk-settings.on-enter-afk-message");
|
||||
onBackMessage = config.getString("afk-settings.on-exit-afk-message");
|
||||
}
|
||||
|
||||
public static AFKManager getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new AFKManager();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
public void updateActivity(Player player) {
|
||||
boolean wasAFK = isAFK(player);
|
||||
lastActive.put(player.getUniqueId(), System.currentTimeMillis());
|
||||
|
||||
if (wasAFK && notifyOnBack) {
|
||||
player.sendMessage(ChatUtil.format(onBackMessage));
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isAFK(Player player) {
|
||||
return (
|
||||
lastActive.containsKey(player.getUniqueId()) &&
|
||||
System.currentTimeMillis() -
|
||||
lastActive.get(player.getUniqueId()) >
|
||||
afkThresholdMillis
|
||||
);
|
||||
}
|
||||
|
||||
public void startAFKChecker() {
|
||||
if (afkCheckerTask == null || afkCheckerTask.isCancelled()) {
|
||||
afkCheckerTask =
|
||||
Bukkit
|
||||
.getScheduler()
|
||||
.runTaskTimerAsynchronously(
|
||||
PlayTimes.getPlugin(PlayTimes.class),
|
||||
() -> {
|
||||
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||
if (isAFK(player)) {
|
||||
if (
|
||||
!afkTime.containsKey(player.getUniqueId()) && notifyOnAfk
|
||||
) {
|
||||
player.sendMessage(ChatUtil.format(onAfkMessage));
|
||||
}
|
||||
afkTime.put(
|
||||
player.getUniqueId(),
|
||||
afkTime.getOrDefault(
|
||||
player.getUniqueId(),
|
||||
getDefaultAfkTime(player.getUniqueId())
|
||||
) +
|
||||
1
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
20L,
|
||||
20L
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public void endAFKChecker() {
|
||||
if (afkCheckerTask != null) {
|
||||
afkCheckerTask.cancel();
|
||||
afkCheckerTask = null;
|
||||
}
|
||||
}
|
||||
|
||||
private Long getDefaultAfkTime(UUID uuid) {
|
||||
DataManager dataManager = DataManager.getInstance();
|
||||
|
||||
if (
|
||||
dataManager.hasDatabase() &&
|
||||
DatabaseManager.getInstance().hasTimeForServer(uuid)
|
||||
) {
|
||||
Map<String, Long> timeMap = DatabaseManager
|
||||
.getInstance()
|
||||
.getTimeForServer(uuid);
|
||||
return timeMap != null ? timeMap.getOrDefault("afktime", 0L) : 0L;
|
||||
} else {
|
||||
return dataManager.getData().getLong("afktime." + uuid, 0L);
|
||||
}
|
||||
}
|
||||
|
||||
public void removePlayer(UUID uuid) {
|
||||
lastActive.remove(uuid);
|
||||
afkTime.remove(uuid);
|
||||
}
|
||||
|
||||
public long getAFKTime(UUID uuid) {
|
||||
return afkTime.getOrDefault(uuid, getDefaultAfkTime(uuid));
|
||||
}
|
||||
|
||||
public void reload() {
|
||||
endAFKChecker();
|
||||
FileConfiguration config = DataManager.getInstance().getConfig();
|
||||
afkThresholdMillis = config.getLong("afk-settings.threshold") * 60L * 1000L;
|
||||
notifyOnAfk = config.getBoolean("afk-settings.broadcast-afk.on-enter-afk");
|
||||
notifyOnBack = config.getBoolean("afk-settings.broadcast-afk.on-exit-afk");
|
||||
onAfkMessage = config.getString("afk-settings.on-enter-afk-message");
|
||||
onBackMessage = config.getString("afk-settings.on-exit-afk-message");
|
||||
startAFKChecker();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package me.codedred.playtimes.afk.listeners;
|
||||
|
||||
import me.codedred.playtimes.afk.AFKManager;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.AsyncPlayerChatEvent;
|
||||
|
||||
public class onChat implements Listener {
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerChat(AsyncPlayerChatEvent event) {
|
||||
AFKManager.getInstance().updateActivity(event.getPlayer());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package me.codedred.playtimes.afk.listeners;
|
||||
|
||||
import me.codedred.playtimes.afk.AFKManager;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
|
||||
public class onInteract implements Listener {
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerInteract(PlayerInteractEvent event) {
|
||||
AFKManager.getInstance().updateActivity(event.getPlayer());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package me.codedred.playtimes.afk.listeners;
|
||||
|
||||
import me.codedred.playtimes.afk.AFKManager;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
|
||||
public class onJoinQuit implements Listener {
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerJoin(PlayerJoinEvent event) {
|
||||
AFKManager.getInstance().updateActivity(event.getPlayer());
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerQuit(PlayerQuitEvent event) {
|
||||
AFKManager.getInstance().removePlayer(event.getPlayer().getUniqueId());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package me.codedred.playtimes.afk.listeners;
|
||||
|
||||
import me.codedred.playtimes.afk.AFKManager;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerMoveEvent;
|
||||
|
||||
public class onMove implements Listener {
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerMove(PlayerMoveEvent event) {
|
||||
if (event.getFrom().getBlock().equals(event.getTo().getBlock())) {
|
||||
return;
|
||||
}
|
||||
AFKManager.getInstance().updateActivity(event.getPlayer());
|
||||
}
|
||||
}
|
||||
@@ -6,8 +6,7 @@ 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;
|
||||
import me.codedred.playtimes.player.OnlinePlayer;
|
||||
import me.codedred.playtimes.models.Message;
|
||||
import me.codedred.playtimes.server.ServerManager;
|
||||
import me.codedred.playtimes.statistics.StatManager;
|
||||
import me.codedred.playtimes.time.TimeConstants;
|
||||
@@ -15,6 +14,7 @@ import me.codedred.playtimes.time.TimeManager;
|
||||
import me.codedred.playtimes.utils.ChatUtil;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
@@ -38,16 +38,38 @@ public class Time implements CommandExecutor {
|
||||
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);
|
||||
String arg = args.length > 0 ? args[0].toLowerCase() : "";
|
||||
|
||||
switch (arg) {
|
||||
case "":
|
||||
handlePlayerCommand(sender);
|
||||
break;
|
||||
case "reload":
|
||||
handleReloadCommand(sender);
|
||||
break;
|
||||
case "reloaddatabase":
|
||||
handleReloadDatabaseCommand(sender);
|
||||
break;
|
||||
case "top":
|
||||
handleTopCommand(sender);
|
||||
break;
|
||||
case "block":
|
||||
handleBlockCommand(sender, args, true);
|
||||
break;
|
||||
case "unblock":
|
||||
handleBlockCommand(sender, args, false);
|
||||
break;
|
||||
case "version":
|
||||
handleVersionCommand(sender);
|
||||
break;
|
||||
case "help":
|
||||
handleHelpCommand(sender);
|
||||
break;
|
||||
default:
|
||||
handleOtherPlayerCommand(sender, args);
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -58,6 +80,9 @@ public class Time implements CommandExecutor {
|
||||
}
|
||||
sender.sendMessage(ChatUtil.format("&6&l*** PlayTimes Help ***"));
|
||||
sender.sendMessage(ChatUtil.format("&e/pt: &7Displays your play time"));
|
||||
sender.sendMessage(
|
||||
ChatUtil.format("&e/pt <player>: &7Displays the play time of <player>")
|
||||
);
|
||||
sender.sendMessage(
|
||||
ChatUtil.format(
|
||||
"&e/pt reload: &7Reloads the PlayTimes plugin configurations"
|
||||
@@ -77,14 +102,11 @@ public class Time implements CommandExecutor {
|
||||
)
|
||||
);
|
||||
sender.sendMessage(
|
||||
ChatUtil.format("&e/pt debug: &7Displays the debug info")
|
||||
);
|
||||
sender.sendMessage(
|
||||
ChatUtil.format("&e/pt <player>: &7Displays the play time of <player>")
|
||||
ChatUtil.format("&e/pt version: &7Displays the version info")
|
||||
);
|
||||
}
|
||||
|
||||
private void handleDebugCommand(CommandSender sender) {
|
||||
private void handleVersionCommand(CommandSender sender) {
|
||||
if (!sender.hasPermission("pt.reload")) {
|
||||
ChatUtil.errno(sender, ChatUtil.ChatTypes.NO_PERMISSION);
|
||||
return;
|
||||
@@ -92,7 +114,7 @@ public class Time implements CommandExecutor {
|
||||
boolean isOnline = ServerManager.getInstance().isOnline();
|
||||
String serverStatus = isOnline ? "Online" : "Offline";
|
||||
|
||||
sender.sendMessage(ChatUtil.format("&6&l*** PlayTimes Debug ***"));
|
||||
sender.sendMessage(ChatUtil.format("&6&l*** PlayTimes Version Info ***"));
|
||||
sender.sendMessage(
|
||||
ChatColor.GOLD +
|
||||
"Server version: " +
|
||||
@@ -103,13 +125,25 @@ public class Time implements CommandExecutor {
|
||||
ChatColor.WHITE +
|
||||
JavaPlugin.getPlugin(PlayTimes.class).getDescription().getVersion() +
|
||||
ChatColor.GOLD +
|
||||
"\nStatManager: " +
|
||||
"\nStat Manager: " +
|
||||
ChatColor.WHITE +
|
||||
StatManager.getInstance().name +
|
||||
ChatColor.GOLD +
|
||||
"\nServerStatus: " +
|
||||
"\nServer Status: " +
|
||||
ChatColor.WHITE +
|
||||
serverStatus
|
||||
serverStatus +
|
||||
ChatColor.GOLD +
|
||||
"\nDatabase connected: " +
|
||||
ChatColor.WHITE +
|
||||
DataManager.getInstance().hasDatabase() +
|
||||
ChatColor.GOLD +
|
||||
"\nAFK Status: " +
|
||||
ChatColor.WHITE +
|
||||
DataManager.getInstance().hasAfkEnabled() +
|
||||
ChatColor.GOLD +
|
||||
"\nUUID Lookup Type: " +
|
||||
ChatColor.WHITE +
|
||||
ServerManager.getInstance().lookupType()
|
||||
);
|
||||
}
|
||||
|
||||
@@ -121,8 +155,20 @@ public class Time implements CommandExecutor {
|
||||
);
|
||||
return;
|
||||
}
|
||||
OnlinePlayer player = new OnlinePlayer((Player) sender);
|
||||
player.sendMessageToTarget();
|
||||
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Player player = (Player) sender;
|
||||
Message message = new Message(
|
||||
sender,
|
||||
player.getUniqueId(),
|
||||
player.getName()
|
||||
);
|
||||
message.sendMessageToTarget();
|
||||
}
|
||||
}
|
||||
.runTaskAsynchronously(JavaPlugin.getPlugin(PlayTimes.class));
|
||||
}
|
||||
|
||||
private void handleReloadCommand(CommandSender sender) {
|
||||
@@ -134,6 +180,27 @@ public class Time implements CommandExecutor {
|
||||
TimeConstants.reload();
|
||||
TimeManager.getInstance().registerTimings();
|
||||
sender.sendMessage(ChatUtil.format("&aPlayTimes Configurations Reloaded!"));
|
||||
if (DataManager.getInstance().hasDatabase()) {
|
||||
sender.sendMessage(
|
||||
ChatUtil.format("&aTrying to reload the Database settings?")
|
||||
);
|
||||
sender.sendMessage(ChatUtil.format(" &e&oTry, /pt reloadDatabase"));
|
||||
}
|
||||
}
|
||||
|
||||
private void handleReloadDatabaseCommand(CommandSender sender) {
|
||||
if (!sender.hasPermission("pt.reload")) {
|
||||
ChatUtil.errno(sender, ChatUtil.ChatTypes.NO_PERMISSION);
|
||||
return;
|
||||
}
|
||||
data.reloadDatabase();
|
||||
PlayTimes.getPlugin(PlayTimes.class).loadDatabase();
|
||||
sender.sendMessage(ChatUtil.format("&aDatabase Reloaded."));
|
||||
sender.sendMessage(
|
||||
ChatUtil.format(
|
||||
"&oIf you are still encountering issues try restarting your server."
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private void handleTopCommand(CommandSender sender) {
|
||||
@@ -232,15 +299,11 @@ public class Time implements CommandExecutor {
|
||||
Objects.requireNonNull(Bukkit.getPlayer(args[0])).getUniqueId();
|
||||
}
|
||||
|
||||
org.bukkit.OfflinePlayer offlinePlayer = Bukkit
|
||||
OfflinePlayer offlinePlayer = Bukkit
|
||||
.getServer()
|
||||
.getOfflinePlayer(target);
|
||||
OfflinePlayer player = new OfflinePlayer(
|
||||
sender,
|
||||
target,
|
||||
offlinePlayer.getName()
|
||||
);
|
||||
player.sendMessageToTarget();
|
||||
Message message = new Message(sender, target, offlinePlayer.getName());
|
||||
message.sendMessageToTarget();
|
||||
}
|
||||
}
|
||||
.runTaskAsynchronously(JavaPlugin.getPlugin(PlayTimes.class));
|
||||
|
||||
@@ -29,17 +29,14 @@ public class TopTime implements CommandExecutor {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(sender instanceof Player player)) {
|
||||
sender.sendMessage("Must be a player to run this command.");
|
||||
return true;
|
||||
}
|
||||
|
||||
DataManager data = DataManager.getInstance();
|
||||
|
||||
if (
|
||||
data.getConfig().getBoolean("top-playtime.enable-cooldown") &&
|
||||
!player.hasPermission("pt.block-cooldown")
|
||||
!sender.hasPermission("pt.block-cooldown") &&
|
||||
sender instanceof Player
|
||||
) {
|
||||
Player player = (Player) sender;
|
||||
if (CoolDownUtil.contains(player.getUniqueId())) {
|
||||
String cooldownMessage = Objects
|
||||
.requireNonNull(data.getConfig().getString("messages.cooldown"))
|
||||
@@ -78,8 +75,8 @@ public class TopTime implements CommandExecutor {
|
||||
String content = data.getConfig().getString("top-playtime.content");
|
||||
|
||||
if (ServerUtils.hasPAPI()) {
|
||||
header = PAPIHolders.getHolders(player, header);
|
||||
footer = PAPIHolders.getHolders(player, footer);
|
||||
header = PAPIHolders.getHolders((Player) sender, header);
|
||||
footer = PAPIHolders.getHolders((Player) sender, footer);
|
||||
}
|
||||
|
||||
sender.sendMessage(header);
|
||||
|
||||
@@ -42,7 +42,8 @@ public class Uptime implements CommandExecutor {
|
||||
.getStringList("uptime.message");
|
||||
|
||||
for (String message : messages) {
|
||||
if (ServerUtils.hasPAPI() && sender instanceof Player player) {
|
||||
if (ServerUtils.hasPAPI() && sender instanceof Player) {
|
||||
Player player = (Player) sender;
|
||||
message = PlaceholderAPI.setPlaceholders(player, message);
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.TabCompleter;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.metadata.MetadataValue;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class TimeTabCompleter implements TabCompleter {
|
||||
@@ -23,7 +24,7 @@ public class TimeTabCompleter implements TabCompleter {
|
||||
if (args.length == 1) {
|
||||
if (sender.hasPermission("pt.use")) {
|
||||
completions.add("top");
|
||||
completions.addAll(getOnlinePlayerNames());
|
||||
completions.addAll(getOnlinePlayerNames(sender));
|
||||
}
|
||||
if (sender.hasPermission("pt.block")) {
|
||||
completions.add("block");
|
||||
@@ -31,7 +32,7 @@ public class TimeTabCompleter implements TabCompleter {
|
||||
}
|
||||
if (sender.hasPermission("pt.reload")) {
|
||||
completions.add("reload");
|
||||
completions.add("debug");
|
||||
completions.add("version");
|
||||
completions.add("help");
|
||||
}
|
||||
}
|
||||
@@ -39,11 +40,24 @@ public class TimeTabCompleter implements TabCompleter {
|
||||
return completions;
|
||||
}
|
||||
|
||||
private List<String> getOnlinePlayerNames() {
|
||||
private List<String> getOnlinePlayerNames(CommandSender sender) {
|
||||
List<String> playerNames = new ArrayList<>();
|
||||
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||
playerNames.add(player.getName());
|
||||
if (
|
||||
!isVanished(player) ||
|
||||
sender.equals(player) ||
|
||||
sender.hasPermission("pt.seevanished")
|
||||
) {
|
||||
playerNames.add(player.getName());
|
||||
}
|
||||
}
|
||||
return playerNames;
|
||||
}
|
||||
|
||||
private boolean isVanished(Player player) {
|
||||
for (MetadataValue meta : player.getMetadata("vanished")) {
|
||||
if (meta.asBoolean()) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,8 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
import me.codedred.playtimes.PlayTimes;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
@@ -23,17 +25,131 @@ public class CustomConfig {
|
||||
}
|
||||
|
||||
public void reloadConfig() {
|
||||
if (this.dataConfigFile == null) this.dataConfigFile =
|
||||
new File(this.plugin.getDataFolder(), name);
|
||||
if (this.dataConfigFile == null) {
|
||||
this.dataConfigFile = new File(this.plugin.getDataFolder(), name);
|
||||
}
|
||||
|
||||
this.dataConfig = YamlConfiguration.loadConfiguration(this.dataConfigFile);
|
||||
|
||||
InputStream defConfigStream = this.plugin.getResource(name);
|
||||
if (defConfigStream != null) {
|
||||
YamlConfiguration defConfig = YamlConfiguration.loadConfiguration(
|
||||
new InputStreamReader(defConfigStream)
|
||||
);
|
||||
this.dataConfig.setDefaults(defConfig);
|
||||
if ("config.yml".equals(name)) checkAndAddDefaults();
|
||||
|
||||
try (InputStream defConfigStream = this.plugin.getResource(name)) {
|
||||
if (defConfigStream != null) {
|
||||
YamlConfiguration defConfig = YamlConfiguration.loadConfiguration(
|
||||
new InputStreamReader(defConfigStream)
|
||||
);
|
||||
this.dataConfig.setDefaults(defConfig);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
this.plugin.getLogger()
|
||||
.log(Level.SEVERE, "Error reading default config", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkAndAddDefaults() {
|
||||
Map<String, Object> requiredKeys = new LinkedHashMap<>();
|
||||
requiredKeys.put("prefix", "&7[&b&lPlayTimes&7]");
|
||||
requiredKeys.put("use-papi-placeholders", false);
|
||||
|
||||
requiredKeys.put(
|
||||
"playtime.message",
|
||||
new String[] {
|
||||
"&b&m=======&b&l[%player%]&b&m=======",
|
||||
"&aPlaytime:&f %playtime%",
|
||||
"&aTimes Joined:&f %timesjoined%",
|
||||
"&aJoin Date:&f %joindate%",
|
||||
"&b&m============================",
|
||||
}
|
||||
);
|
||||
|
||||
requiredKeys.put("playtime.name.second", "s");
|
||||
requiredKeys.put("playtime.name.minute", "min ");
|
||||
requiredKeys.put("playtime.name.hour", "hr ");
|
||||
requiredKeys.put("playtime.name.day", "day ");
|
||||
requiredKeys.put("playtime.name.seconds", "s");
|
||||
requiredKeys.put("playtime.name.minutes", "mins ");
|
||||
requiredKeys.put("playtime.name.hours", "hrs ");
|
||||
requiredKeys.put("playtime.name.days", "days ");
|
||||
requiredKeys.put("playtime.only-hours", false);
|
||||
requiredKeys.put("playtime.show-seconds", true);
|
||||
requiredKeys.put("playtime.show-days", true);
|
||||
requiredKeys.put("playtime.round-numbers", true);
|
||||
|
||||
requiredKeys.put("afk-settings.enabled", false);
|
||||
requiredKeys.put("afk-settings.threshold", 5);
|
||||
requiredKeys.put("afk-settings.broadcast-afk.on-enter-afk", true);
|
||||
requiredKeys.put("afk-settings.broadcast-afk.on-exit-afk", true);
|
||||
requiredKeys.put(
|
||||
"afk-settings.on-enter-afk-message",
|
||||
"&eYou are now marked as AFK."
|
||||
);
|
||||
requiredKeys.put(
|
||||
"afk-settings.on-exit-afk-message",
|
||||
"&eYou are no longer AFK."
|
||||
);
|
||||
requiredKeys.put("afk-settings.cancel-afk.on-player-move", true);
|
||||
requiredKeys.put("afk-settings.cancel-afk.on-player-chat", true);
|
||||
requiredKeys.put("afk-settings.cancel-afk.on-player-interact", true);
|
||||
|
||||
requiredKeys.put(
|
||||
"uptime.message",
|
||||
new String[] {
|
||||
"&b&m============================",
|
||||
"&aServer Uptime:&f %serveruptime%",
|
||||
"&b&m============================",
|
||||
}
|
||||
);
|
||||
|
||||
requiredKeys.put(
|
||||
"top-playtime.header",
|
||||
"&b******&9[&3&lPlayTime Leaderboards&9]&b*****"
|
||||
);
|
||||
requiredKeys.put(
|
||||
"top-playtime.content",
|
||||
"&5%place%) &9&l%player% &9&o- %time%"
|
||||
);
|
||||
requiredKeys.put(
|
||||
"top-playtime.footer",
|
||||
"&b****************************************"
|
||||
);
|
||||
requiredKeys.put("top-playtime.enable-cooldown", true);
|
||||
requiredKeys.put("top-playtime.cooldown-seconds", 60);
|
||||
requiredKeys.put("top-playtime.track-rawtime", false);
|
||||
|
||||
requiredKeys.put("date-format", "MM/dd/yyyy");
|
||||
|
||||
requiredKeys.put("messages.noPermission", "&cYou cannot run this command.");
|
||||
requiredKeys.put("messages.player-not-found", "&cUnable to locate player.");
|
||||
requiredKeys.put(
|
||||
"messages.player-never-joined",
|
||||
"&cThis player has not joined the server."
|
||||
);
|
||||
requiredKeys.put(
|
||||
"messages.cooldown",
|
||||
"&cCommand unavailable for %timeleft% seconds!"
|
||||
);
|
||||
|
||||
requiredKeys.put(
|
||||
"uuid-lookups.what-does-this-do",
|
||||
"https://github.com/CodedRed-Spigot/PlayTimes/wiki/UUID-LOOKUPS"
|
||||
);
|
||||
requiredKeys.put("uuid-lookups.type", "default");
|
||||
|
||||
boolean changesMade = false;
|
||||
for (Map.Entry<String, Object> entry : requiredKeys.entrySet()) {
|
||||
if (!this.dataConfig.contains(entry.getKey())) {
|
||||
this.dataConfig.set(entry.getKey(), entry.getValue());
|
||||
changesMade = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (changesMade) {
|
||||
plugin
|
||||
.getLogger()
|
||||
.info(
|
||||
"Missing configuration keys detected in 'Config.yml'. Adding them now."
|
||||
);
|
||||
saveConfig();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +159,7 @@ public class CustomConfig {
|
||||
}
|
||||
|
||||
public void saveConfig() {
|
||||
if ((this.dataConfig == null) || (this.dataConfigFile == null)) return;
|
||||
if (this.dataConfig == null || this.dataConfigFile == null) return;
|
||||
try {
|
||||
getConfig().save(this.dataConfigFile);
|
||||
} catch (IOException ex) {
|
||||
@@ -57,8 +173,11 @@ public class CustomConfig {
|
||||
}
|
||||
|
||||
public void saveDefaultConfig() {
|
||||
if (this.dataConfigFile == null) this.dataConfigFile =
|
||||
new File(this.plugin.getDataFolder(), name);
|
||||
if (!this.dataConfigFile.exists()) this.plugin.saveResource(name, false);
|
||||
if (this.dataConfigFile == null) {
|
||||
this.dataConfigFile = new File(this.plugin.getDataFolder(), name);
|
||||
}
|
||||
if (!this.dataConfigFile.exists()) {
|
||||
this.plugin.saveResource(name, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,9 @@
|
||||
package me.codedred.playtimes.data;
|
||||
|
||||
import me.codedred.playtimes.PlayTimes;
|
||||
import me.codedred.playtimes.afk.AFKManager;
|
||||
import me.codedred.playtimes.data.database.manager.DatabaseManager;
|
||||
import me.codedred.playtimes.server.ServerManager;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
@@ -44,5 +47,22 @@ public class DataManager {
|
||||
data.reloadConfig();
|
||||
cfg.reloadConfig();
|
||||
db.reloadConfig();
|
||||
ServerManager.getInstance().updateLookupType();
|
||||
if (hasAfkEnabled()) AFKManager.getInstance().reload();
|
||||
}
|
||||
|
||||
public void reloadDatabase() {
|
||||
db.reloadConfig();
|
||||
}
|
||||
|
||||
public boolean hasDatabase() {
|
||||
return (
|
||||
getDBConfig().getBoolean("database-settings.enabled") &&
|
||||
DatabaseManager.getInstance().isConnected()
|
||||
);
|
||||
}
|
||||
|
||||
public boolean hasAfkEnabled() {
|
||||
return getConfig().getBoolean("afk-settings.enabled", false);
|
||||
}
|
||||
}
|
||||
@@ -6,11 +6,14 @@ import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import lombok.Getter;
|
||||
import me.codedred.playtimes.PlayTimes;
|
||||
import me.codedred.playtimes.afk.AFKManager;
|
||||
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 me.codedred.playtimes.statistics.StatManager;
|
||||
import me.codedred.playtimes.statistics.StatisticType;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
@Getter
|
||||
@@ -20,10 +23,17 @@ public class DatabaseManager {
|
||||
|
||||
private DataSource dataSource;
|
||||
private UsersTable usersTable;
|
||||
private boolean connected = false;
|
||||
private final String serverId;
|
||||
|
||||
private Map<UUID, Map<String, Long>> userPlaytimes = new HashMap<>();
|
||||
private Map<UUID, Map<String, Map<String, Long>>> userPlaytimes = new HashMap<>();
|
||||
|
||||
private DatabaseManager() {
|
||||
serverId =
|
||||
DataManager
|
||||
.getInstance()
|
||||
.getDBConfig()
|
||||
.getString("database-settings.serverId");
|
||||
setupDataSource();
|
||||
}
|
||||
|
||||
@@ -54,17 +64,30 @@ public class DatabaseManager {
|
||||
". Accepted Values: 'mysql', 'sqlite'"
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
connected = dataSource != null && dataSource.getConnection() != null;
|
||||
} catch (SQLException e) {
|
||||
Bukkit
|
||||
.getServer()
|
||||
.getLogger()
|
||||
.warning("[PlayTimes] Error thrown from DatabaseManager!");
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isConnected() {
|
||||
return connected;
|
||||
}
|
||||
|
||||
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();
|
||||
if (isConnected()) {
|
||||
this.usersTable = new UsersTable(dataSource);
|
||||
this.usersTable.createTable();
|
||||
} else {
|
||||
Bukkit
|
||||
.getServer()
|
||||
.getLogger()
|
||||
.warning("[PlayTimes] Couldn't connect to Database!");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,49 +98,115 @@ public class DatabaseManager {
|
||||
return this.usersTable;
|
||||
}
|
||||
|
||||
// Called onPlayerJoin
|
||||
public void retrievePlayTime(UUID uuid) {
|
||||
Map<String, Long> timeMap = getUsersTable().getPlaytimesByUuid(uuid);
|
||||
userPlaytimes.put(uuid, timeMap);
|
||||
public boolean retrievePlaytime(UUID uuid) {
|
||||
Map<String, Map<String, Long>> timeMap = getUsersTable()
|
||||
.getPlaytimesByUuid(uuid);
|
||||
if (timeMap != null && !timeMap.isEmpty()) {
|
||||
userPlaytimes.put(uuid, timeMap);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Called onPlayerQuit
|
||||
public void updatePlaytime(UUID uuid, Long playtime) {
|
||||
public void updatePlaytime(UUID uuid, Long playtime, Long afktime) {
|
||||
getUsersTable()
|
||||
.insertOrUpdate(
|
||||
uuid.toString(),
|
||||
DataManager
|
||||
.getInstance()
|
||||
.getDBConfig()
|
||||
.getString("database-settings.serverId"),
|
||||
playtime
|
||||
);
|
||||
userPlaytimes.remove(uuid);
|
||||
.insertOrUpdate(uuid.toString(), serverId, playtime, afktime);
|
||||
|
||||
userPlaytimes
|
||||
.computeIfAbsent(uuid, k -> new HashMap<>())
|
||||
.computeIfAbsent(serverId, k -> new HashMap<>())
|
||||
.put("playtime", playtime);
|
||||
userPlaytimes.get(uuid).get(serverId).put("afktime", afktime);
|
||||
}
|
||||
|
||||
// Given the serverId returns the playtime from that server
|
||||
public Long getPlayTimeForServer(UUID uuid, String server) {
|
||||
if (
|
||||
public boolean hasTimeForServer(UUID uuid, String server) {
|
||||
if (!userPlaytimes.containsKey(uuid)) {
|
||||
return retrievePlaytime(uuid);
|
||||
}
|
||||
return (
|
||||
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);
|
||||
public boolean hasTimeForServer(UUID uuid) {
|
||||
return (hasTimeForServer(uuid, serverId));
|
||||
}
|
||||
|
||||
if (userPlaytimeMap != null) {
|
||||
for (Long individualPlaytime : userPlaytimeMap.values()) {
|
||||
playtime += individualPlaytime;
|
||||
public Map<String, Long> getTimeForServer(UUID uuid, String server) {
|
||||
return userPlaytimes.get(uuid).get(server);
|
||||
}
|
||||
|
||||
public Map<String, Long> getTimeForServer(UUID uuid) {
|
||||
return getTimeForServer(uuid, serverId);
|
||||
}
|
||||
|
||||
public Long getTotalRawtime(UUID uuid) {
|
||||
Long rawtime = 0L;
|
||||
Map<String, Map<String, Long>> userTimeData = userPlaytimes.get(uuid);
|
||||
if (userTimeData != null) {
|
||||
for (Map.Entry<String, Map<String, Long>> entry : userTimeData.entrySet()) {
|
||||
String server = entry.getKey();
|
||||
Map<String, Long> serverData = entry.getValue();
|
||||
if (!server.equals(serverId)) {
|
||||
Long individualRawtime = serverData.getOrDefault("playtime", 0L);
|
||||
rawtime += individualRawtime;
|
||||
}
|
||||
}
|
||||
}
|
||||
StatManager stats = StatManager.getInstance();
|
||||
Long currentServerRawtime =
|
||||
stats.getPlayerStat(uuid, StatisticType.PLAYTIME) / 20;
|
||||
rawtime += currentServerRawtime;
|
||||
return rawtime;
|
||||
}
|
||||
|
||||
public Long getTotalAfktime(UUID uuid) {
|
||||
Long afktime = 0L;
|
||||
Map<String, Map<String, Long>> userTimeData = userPlaytimes.get(uuid);
|
||||
if (userTimeData != null) {
|
||||
for (Map.Entry<String, Map<String, Long>> entry : userTimeData.entrySet()) {
|
||||
String server = entry.getKey();
|
||||
Map<String, Long> serverData = entry.getValue();
|
||||
if (!server.equals(serverId)) {
|
||||
Long individualAfktime = serverData.getOrDefault("afktime", 0L);
|
||||
afktime += individualAfktime;
|
||||
}
|
||||
}
|
||||
}
|
||||
long currentServerAfkTime = AFKManager.getInstance().getAFKTime(uuid);
|
||||
afktime += currentServerAfkTime;
|
||||
return afktime;
|
||||
}
|
||||
|
||||
// Calculate the total playtime after subtracting total afktime
|
||||
public Long getTotalPlaytime(UUID uuid) {
|
||||
Long totalPlaytime = 0L;
|
||||
Long totalAfktime = 0L;
|
||||
|
||||
Map<String, Map<String, Long>> userTimeData = userPlaytimes.get(uuid);
|
||||
|
||||
if (userTimeData != null) {
|
||||
for (Map.Entry<String, Map<String, Long>> entry : userTimeData.entrySet()) {
|
||||
String server = entry.getKey();
|
||||
Map<String, Long> serverData = entry.getValue();
|
||||
|
||||
if (!server.equals(serverId)) {
|
||||
totalPlaytime += serverData.getOrDefault("playtime", 0L);
|
||||
totalAfktime += serverData.getOrDefault("afktime", 0L);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return playtime;
|
||||
StatManager stats = StatManager.getInstance();
|
||||
Long currentServerPlaytime =
|
||||
stats.getPlayerStat(uuid, StatisticType.PLAYTIME) / 20;
|
||||
long afkTime = AFKManager.getInstance().getAFKTime(uuid);
|
||||
|
||||
totalPlaytime += currentServerPlaytime;
|
||||
totalAfktime += afkTime;
|
||||
|
||||
return totalPlaytime - totalAfktime;
|
||||
}
|
||||
|
||||
public void purgeOldPlaytimeData() {
|
||||
@@ -125,10 +214,6 @@ public class DatabaseManager {
|
||||
.getLogger()
|
||||
.info("[PlayTimes] Initiating purge of outdated playtime data...");
|
||||
|
||||
String serverId = DataManager
|
||||
.getInstance()
|
||||
.getDBConfig()
|
||||
.getString("database-settings.serverId");
|
||||
int months = DataManager
|
||||
.getInstance()
|
||||
.getDBConfig()
|
||||
|
||||
@@ -27,6 +27,7 @@ public class UsersTable {
|
||||
"`uniqueId` VARCHAR(36) NOT NULL," +
|
||||
"`serverId` VARCHAR(255) NOT NULL," +
|
||||
"`playtime` BIGINT NOT NULL DEFAULT 0," +
|
||||
"`afktime` BIGINT NOT NULL DEFAULT 0," +
|
||||
"`lastUpdated` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP," +
|
||||
"PRIMARY KEY (`uniqueId`, `serverId`))",
|
||||
TABLE_NAME
|
||||
@@ -44,11 +45,16 @@ public class UsersTable {
|
||||
}
|
||||
}
|
||||
|
||||
public void insertOrUpdate(String uuid, String serverId, long playtime) {
|
||||
public void insertOrUpdate(
|
||||
String uuid,
|
||||
String serverId,
|
||||
long playtime,
|
||||
long afktime
|
||||
) {
|
||||
Async.run(() -> {
|
||||
String query = String.format(
|
||||
"INSERT INTO `%s` (`uniqueId`, `serverId`, `playtime`) VALUES (?, ?, ?) " +
|
||||
"ON DUPLICATE KEY UPDATE `playtime` = ?",
|
||||
"INSERT INTO `%s` (`uniqueId`, `serverId`, `playtime`, `afktime`) VALUES (?, ?, ?, ?) " +
|
||||
"ON DUPLICATE KEY UPDATE `playtime` = ?, `afktime` = ?",
|
||||
TABLE_NAME
|
||||
);
|
||||
|
||||
@@ -59,7 +65,9 @@ public class UsersTable {
|
||||
preparedStatement.setString(1, uuid);
|
||||
preparedStatement.setString(2, serverId);
|
||||
preparedStatement.setLong(3, playtime);
|
||||
preparedStatement.setLong(4, playtime);
|
||||
preparedStatement.setLong(4, afktime);
|
||||
preparedStatement.setLong(5, playtime);
|
||||
preparedStatement.setLong(6, afktime);
|
||||
|
||||
preparedStatement.executeUpdate();
|
||||
} catch (SQLException e) {
|
||||
@@ -68,8 +76,8 @@ public class UsersTable {
|
||||
});
|
||||
}
|
||||
|
||||
public Map<String, Long> getPlaytimesByUuid(UUID uuid) {
|
||||
Map<String, Long> playtimes = new HashMap<>();
|
||||
public Map<String, Map<String, Long>> getPlaytimesByUuid(UUID uuid) {
|
||||
Map<String, Map<String, Long>> timesMap = new HashMap<>();
|
||||
|
||||
try (
|
||||
Connection conn = dataSource.getConnection();
|
||||
@@ -83,14 +91,20 @@ public class UsersTable {
|
||||
while (resultSet.next()) {
|
||||
String serverId = resultSet.getString("serverId");
|
||||
long playtime = resultSet.getLong("playtime");
|
||||
playtimes.put(serverId, playtime);
|
||||
long afktime = resultSet.getLong("afktime");
|
||||
|
||||
Map<String, Long> timeData = new HashMap<>();
|
||||
timeData.put("playtime", playtime);
|
||||
timeData.put("afktime", afktime);
|
||||
|
||||
timesMap.put(serverId, timeData);
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return playtimes;
|
||||
return timesMap;
|
||||
}
|
||||
|
||||
public Map<String, Timestamp> getLastUpdatedTimesByUuid(UUID uuid) {
|
||||
|
||||
@@ -2,6 +2,7 @@ package me.codedred.playtimes.listeners;
|
||||
|
||||
import java.util.UUID;
|
||||
import me.codedred.playtimes.PlayTimes;
|
||||
import me.codedred.playtimes.afk.AFKManager;
|
||||
import me.codedred.playtimes.data.DataManager;
|
||||
import me.codedred.playtimes.data.database.manager.DatabaseManager;
|
||||
import me.codedred.playtimes.statistics.StatManager;
|
||||
@@ -20,9 +21,9 @@ public class Join implements Listener {
|
||||
DataManager data = DataManager.getInstance();
|
||||
|
||||
// Database
|
||||
if (data.getDBConfig().getBoolean("database-settings.enabled")) {
|
||||
if (data.hasDatabase()) {
|
||||
DatabaseManager dbManager = DatabaseManager.getInstance();
|
||||
dbManager.retrievePlayTime(uuid);
|
||||
dbManager.retrievePlaytime(uuid);
|
||||
|
||||
// hacky bug fix that will update data again if database query was too slow.
|
||||
// this bug only arises when switching servers super fast!
|
||||
@@ -31,7 +32,7 @@ public class Join implements Listener {
|
||||
.runTaskLaterAsynchronously(
|
||||
PlayTimes.getPlugin(PlayTimes.class),
|
||||
() -> {
|
||||
dbManager.retrievePlayTime(uuid);
|
||||
dbManager.retrievePlaytime(uuid);
|
||||
},
|
||||
20L * 30
|
||||
);
|
||||
@@ -61,6 +62,16 @@ public class Join implements Listener {
|
||||
long time = StatManager
|
||||
.getInstance()
|
||||
.getPlayerStat(uuid, StatisticType.PLAYTIME);
|
||||
|
||||
if (
|
||||
!data.getConfig().getBoolean("top-playtime.track-rawtime", false) &&
|
||||
data.hasAfkEnabled()
|
||||
) {
|
||||
time -=
|
||||
AFKManager.getInstance().getAFKTime(event.getPlayer().getUniqueId()) *
|
||||
20;
|
||||
}
|
||||
|
||||
leaderboardSection.set(uuid.toString(), time);
|
||||
|
||||
data.saveData();
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package me.codedred.playtimes.listeners;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import me.codedred.playtimes.afk.AFKManager;
|
||||
import me.codedred.playtimes.data.DataManager;
|
||||
import me.codedred.playtimes.data.database.manager.DatabaseManager;
|
||||
import me.codedred.playtimes.statistics.StatManager;
|
||||
@@ -17,18 +19,26 @@ public class Quit implements Listener {
|
||||
DataManager data = DataManager.getInstance();
|
||||
|
||||
// Database
|
||||
if (data.getDBConfig().getBoolean("database-settings.enabled")) {
|
||||
DatabaseManager dbManager = DatabaseManager.getInstance();
|
||||
dbManager.updatePlaytime(
|
||||
uuid,
|
||||
StatManager
|
||||
.getInstance()
|
||||
.getPlayerStat(
|
||||
event.getPlayer().getUniqueId(),
|
||||
StatisticType.PLAYTIME
|
||||
) /
|
||||
20
|
||||
);
|
||||
if (data.hasDatabase()) {
|
||||
CompletableFuture.runAsync(() -> {
|
||||
DatabaseManager dbManager = DatabaseManager.getInstance();
|
||||
dbManager.updatePlaytime(
|
||||
uuid,
|
||||
StatManager
|
||||
.getInstance()
|
||||
.getPlayerStat(uuid, StatisticType.PLAYTIME) /
|
||||
20,
|
||||
AFKManager.getInstance().getAFKTime(uuid)
|
||||
);
|
||||
});
|
||||
} else {
|
||||
// Save AFK time in data.yml
|
||||
CompletableFuture.runAsync(() -> {
|
||||
data
|
||||
.getData()
|
||||
.set("afktime." + uuid, AFKManager.getInstance().getAFKTime(uuid));
|
||||
data.saveData();
|
||||
});
|
||||
}
|
||||
|
||||
// Leaderboard
|
||||
@@ -37,10 +47,19 @@ public class Quit implements Listener {
|
||||
return;
|
||||
}
|
||||
|
||||
StatManager statManager = StatManager.getInstance();
|
||||
long playtime = statManager.getPlayerStat(uuid, StatisticType.PLAYTIME);
|
||||
data.getData().set("leaderboard." + uuid, playtime);
|
||||
// Run leaderboard update
|
||||
CompletableFuture.runAsync(() -> {
|
||||
StatManager statManager = StatManager.getInstance();
|
||||
long playtime = statManager.getPlayerStat(uuid, StatisticType.PLAYTIME);
|
||||
if (
|
||||
!data.getConfig().getBoolean("top-playtime.track-rawtime", false) &&
|
||||
data.hasAfkEnabled()
|
||||
) {
|
||||
playtime -= AFKManager.getInstance().getAFKTime(uuid) * 20;
|
||||
}
|
||||
|
||||
data.saveData();
|
||||
data.getData().set("leaderboard." + uuid, playtime);
|
||||
data.saveData();
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package me.codedred.playtimes.models;
|
||||
|
||||
import java.util.*;
|
||||
import me.codedred.playtimes.afk.AFKManager;
|
||||
import me.codedred.playtimes.data.DataManager;
|
||||
import me.codedred.playtimes.statistics.StatManager;
|
||||
import me.codedred.playtimes.statistics.StatisticType;
|
||||
@@ -63,6 +64,7 @@ public class Leaderboard {
|
||||
*/
|
||||
private void updateTimes(Map<String, Integer> topTen) {
|
||||
StatManager statManager = StatManager.getInstance();
|
||||
DataManager dataManager = DataManager.getInstance();
|
||||
List<Map.Entry<String, Integer>> list = new ArrayList<>(topTen.entrySet());
|
||||
|
||||
for (Map.Entry<String, Integer> entry : list) {
|
||||
@@ -71,6 +73,17 @@ public class Leaderboard {
|
||||
UUID.fromString(uuid),
|
||||
StatisticType.PLAYTIME
|
||||
);
|
||||
|
||||
if (
|
||||
!dataManager
|
||||
.getConfig()
|
||||
.getBoolean("top-playtime.track-rawtime", false) &&
|
||||
dataManager.hasAfkEnabled()
|
||||
) {
|
||||
latestTime -=
|
||||
AFKManager.getInstance().getAFKTime(UUID.fromString(uuid)) * 20;
|
||||
}
|
||||
|
||||
topTen.put(uuid, latestTime);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,228 @@
|
||||
package me.codedred.playtimes.models;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import me.codedred.playtimes.afk.AFKManager;
|
||||
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;
|
||||
import me.codedred.playtimes.utils.ChatUtil;
|
||||
import me.codedred.playtimes.utils.PAPIHolders;
|
||||
import me.codedred.playtimes.utils.ServerUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
public class Message {
|
||||
|
||||
private final CommandSender sender;
|
||||
private final UUID targetUUID;
|
||||
private final String targetName;
|
||||
private List<String> message;
|
||||
|
||||
private final DataManager dataManager;
|
||||
private final StatManager statManager;
|
||||
private final TimeManager timeManager;
|
||||
|
||||
/**
|
||||
* Constructor for Message.
|
||||
* Initializes the message for the target player.
|
||||
*
|
||||
* @param sender The command sender.
|
||||
* @param targetUUID The UUID of the offline player.
|
||||
* @param targetName The name of the offline player.
|
||||
*/
|
||||
public Message(CommandSender sender, UUID targetUUID, String targetName) {
|
||||
this.sender = sender;
|
||||
this.targetUUID = targetUUID;
|
||||
this.targetName = targetName;
|
||||
|
||||
this.dataManager = DataManager.getInstance();
|
||||
this.statManager = StatManager.getInstance();
|
||||
this.timeManager = TimeManager.getInstance();
|
||||
|
||||
this.message = buildMessage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the message to be sent to the sender about the target 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 = dataManager
|
||||
.getConfig()
|
||||
.getStringList("playtime.message");
|
||||
long rawTime = statManager.getPlayerStat(
|
||||
targetUUID,
|
||||
StatisticType.PLAYTIME
|
||||
);
|
||||
long afkTime = AFKManager.getInstance().getAFKTime(targetUUID);
|
||||
|
||||
if (dataManager.hasDatabase()) {
|
||||
DatabaseManager dbManager = DatabaseManager.getInstance();
|
||||
dbManager.updatePlaytime(targetUUID, rawTime / 20, afkTime);
|
||||
}
|
||||
|
||||
if (ServerUtils.hasPAPI()) {
|
||||
builtMessage = applyPAPIPlaceholders(builtMessage);
|
||||
}
|
||||
|
||||
return processMessageWithReplacements(
|
||||
builtMessage,
|
||||
prepareReplacements(rawTime, afkTime)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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(targetUUID), msg)
|
||||
);
|
||||
}
|
||||
return papiMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares a map of replacements to be used in the message.
|
||||
*
|
||||
* @param rawTime The playtime statistic to format and include in the replacements.
|
||||
* @param afkTime The afktime 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, long afkTime) {
|
||||
Map<String, String> replacements = new HashMap<>();
|
||||
replacements.put("%time%", timeManager.buildFormat(rawTime / 20 - afkTime));
|
||||
replacements.put(
|
||||
"%playtime%",
|
||||
timeManager.buildFormat(rawTime / 20 - afkTime)
|
||||
);
|
||||
replacements.put("%rawtime%", timeManager.buildFormat(rawTime / 20));
|
||||
replacements.put("%afktime%", timeManager.buildFormat(afkTime));
|
||||
replacements.put("%player%", targetName);
|
||||
replacements.put(
|
||||
"%timesjoined%",
|
||||
Long.toString(
|
||||
statManager.getPlayerStat(targetUUID, StatisticType.TIMES_JOINED)
|
||||
)
|
||||
);
|
||||
replacements.put("%joindate%", statManager.getJoinDate(targetUUID));
|
||||
|
||||
if (dataManager.hasDatabase()) {
|
||||
DatabaseManager dbManager = DatabaseManager.getInstance();
|
||||
|
||||
long globalPlaytime = dbManager.getTotalPlaytime(targetUUID);
|
||||
long globalRawtime = dbManager.getTotalRawtime(targetUUID);
|
||||
long globalAfktime = dbManager.getTotalAfktime(targetUUID);
|
||||
|
||||
replacements.put(
|
||||
"%global_playtime%",
|
||||
timeManager.buildFormat(globalPlaytime)
|
||||
);
|
||||
replacements.put(
|
||||
"%global_rawtime%",
|
||||
timeManager.buildFormat(globalRawtime)
|
||||
);
|
||||
replacements.put(
|
||||
"%global_afktime%",
|
||||
timeManager.buildFormat(globalAfktime)
|
||||
);
|
||||
}
|
||||
|
||||
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 hasDatabase = dataManager.hasDatabase();
|
||||
DatabaseManager dbManager = hasDatabase
|
||||
? DatabaseManager.getInstance()
|
||||
: null;
|
||||
Pattern pattern = Pattern.compile("%(rawtime|afktime|playtime)_(\\w+)%");
|
||||
|
||||
for (String msg : message) {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
if (hasDatabase && dbManager != null) {
|
||||
Matcher matcher = pattern.matcher(msg);
|
||||
while (matcher.find()) {
|
||||
String placeholderType = matcher.group(1);
|
||||
String serverId = matcher.group(2);
|
||||
Long timeValue = 0L;
|
||||
|
||||
if (dbManager.hasTimeForServer(targetUUID, serverId)) {
|
||||
Map<String, Long> timeForServer = dbManager.getTimeForServer(
|
||||
targetUUID,
|
||||
serverId
|
||||
);
|
||||
timeValue =
|
||||
timeForServer.getOrDefault(
|
||||
placeholderType.equals("rawtime")
|
||||
? "playtime"
|
||||
: placeholderType,
|
||||
0L
|
||||
);
|
||||
if (placeholderType.equals("playtime")) {
|
||||
timeValue -= timeForServer.getOrDefault("afktime", 0L);
|
||||
}
|
||||
}
|
||||
|
||||
matcher.appendReplacement(sb, timeManager.buildFormat(timeValue));
|
||||
}
|
||||
matcher.appendTail(sb);
|
||||
msg = sb.toString();
|
||||
}
|
||||
|
||||
for (Map.Entry<String, String> entry : replacements.entrySet()) {
|
||||
msg =
|
||||
msg.replace(
|
||||
entry.getKey(),
|
||||
entry.getValue() != null ? entry.getValue() : entry.getKey()
|
||||
);
|
||||
}
|
||||
|
||||
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,193 +0,0 @@
|
||||
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;
|
||||
import me.codedred.playtimes.utils.ChatUtil;
|
||||
import me.codedred.playtimes.utils.PAPIHolders;
|
||||
import me.codedred.playtimes.utils.ServerUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
public class OfflinePlayer {
|
||||
|
||||
private final CommandSender sender;
|
||||
private final UUID target;
|
||||
private final String name;
|
||||
private List<String> message;
|
||||
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
return processMessageWithReplacements(
|
||||
builtMessage,
|
||||
prepareReplacements(rawTime, statManager, timeManager)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 (
|
||||
DataManager
|
||||
.getInstance()
|
||||
.getDBConfig()
|
||||
.getBoolean("database-settings.enabled")
|
||||
) {
|
||||
replacements.put("%PlayTimes_db_serverId%", "DYNAMIC");
|
||||
replacements.put(
|
||||
"%PlayTimes_total%",
|
||||
timeManager.buildFormat(
|
||||
DatabaseManager.getInstance().getTotalPlayTime(target)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
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,200 +0,0 @@
|
||||
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;
|
||||
import me.codedred.playtimes.utils.ChatUtil;
|
||||
import me.codedred.playtimes.utils.PAPIHolders;
|
||||
import me.codedred.playtimes.utils.ServerUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class OnlinePlayer {
|
||||
|
||||
private final Player target;
|
||||
private final List<String> message;
|
||||
private final DataManager dataManager;
|
||||
private final StatManager statManager;
|
||||
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();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
return processMessageWithReplacements(
|
||||
builtMessage,
|
||||
prepareReplacements(rawTime)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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())
|
||||
);
|
||||
|
||||
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())
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
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");
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,16 +9,26 @@ public class ServerManager {
|
||||
|
||||
private static final ServerManager instance = new ServerManager();
|
||||
|
||||
public enum LookUpTypes {
|
||||
OFFLINE,
|
||||
ONLINE,
|
||||
}
|
||||
|
||||
public static ServerManager getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
private ServerStatus status;
|
||||
private LookUpTypes lookupType = LookUpTypes.ONLINE;
|
||||
|
||||
public void register() {
|
||||
if (Bukkit.getOnlineMode()) status = new ServerOnline(); else status =
|
||||
new ServerOffline();
|
||||
if (Bukkit.getOnlineMode()) {
|
||||
status = new ServerOnline();
|
||||
} else {
|
||||
status = new ServerOffline();
|
||||
}
|
||||
cleanLeaderboard();
|
||||
updateLookupType();
|
||||
}
|
||||
|
||||
public ServerStatus getStatus() {
|
||||
@@ -37,6 +47,37 @@ public class ServerManager {
|
||||
return getStatus().isOnline();
|
||||
}
|
||||
|
||||
public LookUpTypes lookupType() {
|
||||
return lookupType;
|
||||
}
|
||||
|
||||
public void updateLookupType() {
|
||||
DataManager dataManager = DataManager.getInstance();
|
||||
boolean databaseEnabled = dataManager
|
||||
.getDBConfig()
|
||||
.getBoolean("database-settings.enabled");
|
||||
|
||||
boolean isSetToOffline = dataManager
|
||||
.getConfig()
|
||||
.getString("uuid-lookups.type")
|
||||
.equalsIgnoreCase("offline");
|
||||
|
||||
boolean isSetToOnline = dataManager
|
||||
.getConfig()
|
||||
.getString("uuid-lookups.type")
|
||||
.equalsIgnoreCase("online");
|
||||
|
||||
boolean serverOnline = isOnline();
|
||||
|
||||
if (isSetToOnline) lookupType = LookUpTypes.ONLINE; else if (
|
||||
(!serverOnline && !databaseEnabled) || isSetToOffline
|
||||
) {
|
||||
lookupType = LookUpTypes.OFFLINE;
|
||||
} else {
|
||||
lookupType = LookUpTypes.ONLINE;
|
||||
}
|
||||
}
|
||||
|
||||
private void cleanLeaderboard() {
|
||||
DataManager data = DataManager.getInstance();
|
||||
if (!data.getData().contains("leaderboard")) return;
|
||||
|
||||
@@ -9,32 +9,70 @@ import java.io.InputStreamReader;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.UUID;
|
||||
import me.codedred.playtimes.server.ServerManager.LookUpTypes;
|
||||
import me.codedred.playtimes.statistics.StatManager;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
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)) {
|
||||
UUID offlineUUID = null;
|
||||
Player onlinePlayer = Bukkit.getServer().getPlayer(name);
|
||||
if (onlinePlayer != null) {
|
||||
offlineUUID = onlinePlayer.getUniqueId();
|
||||
}
|
||||
|
||||
if (offlineUUID == null) {
|
||||
OfflinePlayer offlinePlayers[] = Bukkit.getServer().getOfflinePlayers();
|
||||
int playerIndex = 0;
|
||||
while ((playerIndex < offlinePlayers.length) && (offlineUUID == null)) {
|
||||
if (offlinePlayers[playerIndex].getName().equalsIgnoreCase(name)) {
|
||||
offlineUUID = offlinePlayers[playerIndex].getUniqueId();
|
||||
}
|
||||
playerIndex = playerIndex + 1;
|
||||
}
|
||||
}
|
||||
if (offlineUUID != null) {
|
||||
return offlineUUID;
|
||||
} else {
|
||||
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);
|
||||
UUID uuid;
|
||||
|
||||
if (ServerManager.getInstance().lookupType() == LookUpTypes.OFFLINE) {
|
||||
String fixedName = rootobj.get("name").getAsString();
|
||||
uuid =
|
||||
UUID.nameUUIDFromBytes(
|
||||
("OfflinePlayer:" + fixedName).getBytes(StandardCharsets.UTF_8)
|
||||
);
|
||||
} else {
|
||||
String id = rootobj.get("id").getAsString();
|
||||
String uuidWithDashes = id.replaceAll(
|
||||
"(\\w{8})(\\w{4})(\\w{4})(\\w{4})(\\w{12})",
|
||||
"$1-$2-$3-$4-$5"
|
||||
);
|
||||
|
||||
uuid = UUID.fromString(uuidWithDashes);
|
||||
}
|
||||
|
||||
if (!StatManager.getInstance().hasJoinedBefore(uuid)) {
|
||||
return null;
|
||||
}
|
||||
return uuid;
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
}
|
||||
return uuid;
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
package me.codedred.playtimes.server;
|
||||
|
||||
import com.google.gson.*;
|
||||
import me.codedred.playtimes.statistics.StatManager;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@@ -12,35 +8,43 @@ import java.io.InputStreamReader;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.UUID;
|
||||
import me.codedred.playtimes.statistics.StatManager;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ServerOnline implements ServerStatus {
|
||||
|
||||
@Override
|
||||
public UUID getUUID(@NotNull String name) {
|
||||
UUID uuid = Bukkit.getOfflinePlayer(name).getUniqueId();
|
||||
if (StatManager.getInstance().hasJoinedBefore(uuid)) {
|
||||
return null;
|
||||
}
|
||||
return uuid;
|
||||
@Override
|
||||
public UUID getUUID(@NotNull String name) {
|
||||
UUID uuid = Bukkit.getServer().getOfflinePlayer(name).getUniqueId();
|
||||
if (!StatManager.getInstance().hasJoinedBefore(uuid)) {
|
||||
return null;
|
||||
}
|
||||
return uuid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOnline() {
|
||||
return true;
|
||||
@Override
|
||||
public boolean isOnline() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@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)
|
||||
);
|
||||
JsonElement root = JsonParser.parseReader(rd);
|
||||
|
||||
JsonObject rootObj = root.getAsJsonObject();
|
||||
|
||||
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));
|
||||
JsonElement root = JsonParser.parseReader(rd);
|
||||
|
||||
JsonObject rootObj = root.getAsJsonObject();
|
||||
|
||||
return rootObj.get("name").getAsString();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return "User Not Found";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,10 +22,12 @@ public class LegacyStats implements Stats {
|
||||
JsonObject jsonObject = new Gson()
|
||||
.fromJson(new FileReader(playerStatistics), JsonObject.class);
|
||||
|
||||
return switch (type) {
|
||||
case PLAYTIME -> jsonObject.get("stat.playOneMinute").getAsLong();
|
||||
case TIMES_JOINED -> jsonObject.get("stat.leaveGame").getAsLong();
|
||||
};
|
||||
switch (type) {
|
||||
case PLAYTIME:
|
||||
return jsonObject.get("stat.playOneMinute").getAsLong();
|
||||
case TIMES_JOINED:
|
||||
return jsonObject.get("stat.leaveGame").getAsLong();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
//e.printStackTrace();
|
||||
}
|
||||
@@ -51,6 +53,7 @@ public class LegacyStats implements Stats {
|
||||
DataManager.getInstance().getConfig().getString("date-format")
|
||||
);
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
|
||||
if (player == null) {
|
||||
calendar.setTimeInMillis(Bukkit.getOfflinePlayer(uuid).getFirstPlayed());
|
||||
return simpleDateFormat.format(calendar.getTime());
|
||||
@@ -58,6 +61,7 @@ public class LegacyStats implements Stats {
|
||||
calendar.setTimeInMillis(player.getFirstPlayed());
|
||||
return simpleDateFormat.format(calendar.getTime());
|
||||
}
|
||||
|
||||
return "Never Joined";
|
||||
}
|
||||
}
|
||||
@@ -22,25 +22,21 @@ public class RisenStats implements Stats {
|
||||
);
|
||||
|
||||
File playerStatistics = new File(worldFolder, uuid + ".json");
|
||||
|
||||
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");
|
||||
|
||||
switch (type) {
|
||||
case PLAYTIME -> {
|
||||
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 -> {
|
||||
case TIMES_JOINED:
|
||||
return passenger.get("minecraft:leave_game").getAsLong();
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
//e.printStackTrace();
|
||||
@@ -51,10 +47,14 @@ public class RisenStats implements Stats {
|
||||
|
||||
@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;
|
||||
};
|
||||
switch (type) {
|
||||
case PLAYTIME:
|
||||
return player.getStatistic(Statistic.PLAY_ONE_MINUTE);
|
||||
case TIMES_JOINED:
|
||||
return player.getStatistic(Statistic.LEAVE_GAME) + 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -70,6 +70,7 @@ public class RisenStats implements Stats {
|
||||
DataManager.getInstance().getConfig().getString("date-format")
|
||||
);
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
|
||||
if (player == null) {
|
||||
calendar.setTimeInMillis(Bukkit.getOfflinePlayer(uuid).getFirstPlayed());
|
||||
return simpleDateFormat.format(calendar.getTime());
|
||||
@@ -77,6 +78,7 @@ public class RisenStats implements Stats {
|
||||
calendar.setTimeInMillis(player.getFirstPlayed());
|
||||
return simpleDateFormat.format(calendar.getTime());
|
||||
}
|
||||
|
||||
return "Never Joined";
|
||||
}
|
||||
}
|
||||
@@ -20,24 +20,21 @@ public class RisingStats implements Stats {
|
||||
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);
|
||||
|
||||
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 TIMES_JOINED -> passenger
|
||||
.get("minecraft:leave_game")
|
||||
.getAsLong();
|
||||
};
|
||||
switch (type) {
|
||||
case PLAYTIME:
|
||||
return passenger.get("minecraft:play_one_minute").getAsLong();
|
||||
case TIMES_JOINED:
|
||||
return passenger.get("minecraft:leave_game").getAsLong();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
//e.printStackTrace();
|
||||
}
|
||||
@@ -47,10 +44,14 @@ public class RisingStats implements Stats {
|
||||
|
||||
@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;
|
||||
};
|
||||
switch (type) {
|
||||
case PLAYTIME:
|
||||
return player.getStatistic(Statistic.PLAY_ONE_MINUTE);
|
||||
case TIMES_JOINED:
|
||||
return player.getStatistic(Statistic.LEAVE_GAME) + 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -66,6 +67,7 @@ public class RisingStats implements Stats {
|
||||
DataManager.getInstance().getConfig().getString("date-format")
|
||||
);
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
|
||||
if (player == null) {
|
||||
calendar.setTimeInMillis(Bukkit.getOfflinePlayer(uuid).getFirstPlayed());
|
||||
return simpleDateFormat.format(calendar.getTime());
|
||||
@@ -73,6 +75,7 @@ public class RisingStats implements Stats {
|
||||
calendar.setTimeInMillis(player.getFirstPlayed());
|
||||
return simpleDateFormat.format(calendar.getTime());
|
||||
}
|
||||
|
||||
return "Never Joined";
|
||||
}
|
||||
}
|
||||
@@ -42,7 +42,7 @@ public class StatManager {
|
||||
}
|
||||
|
||||
public boolean hasJoinedBefore(UUID uuid) {
|
||||
return !getStats().hasJoinedBefore(uuid);
|
||||
return getStats().hasJoinedBefore(uuid);
|
||||
}
|
||||
|
||||
public String getJoinDate(UUID uuid) {
|
||||
|
||||
@@ -1,31 +1,28 @@
|
||||
package me.codedred.playtimes.time;
|
||||
|
||||
import me.codedred.playtimes.data.DataManager;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
|
||||
public class TimeConstants {
|
||||
|
||||
private static String second, seconds, minute, minutes, hour, hours, day, days;
|
||||
private static boolean rounded;
|
||||
|
||||
static {
|
||||
reload();
|
||||
}
|
||||
|
||||
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");
|
||||
FileConfiguration data = DataManager.getInstance().getConfig();
|
||||
second = data.getString("playtime.name.second");
|
||||
seconds = data.getString("playtime.name.seconds");
|
||||
minute = data.getString("playtime.name.minute");
|
||||
minutes = data.getString("playtime.name.minutes");
|
||||
hour = data.getString("playtime.name.hour");
|
||||
hours = data.getString("playtime.name.hours");
|
||||
day = data.getString("playtime.name.day");
|
||||
days = data.getString("playtime.name.days");
|
||||
rounded = data.getBoolean("playtime.round-numbers");
|
||||
}
|
||||
|
||||
public static String getSecond() {
|
||||
@@ -59,4 +56,8 @@ public class TimeConstants {
|
||||
public static String getDays() {
|
||||
return days;
|
||||
}
|
||||
|
||||
public static boolean getRounded() {
|
||||
return rounded;
|
||||
}
|
||||
}
|
||||
@@ -7,8 +7,15 @@ public class OnlyHours implements Timings {
|
||||
|
||||
@Override
|
||||
public String buildFormat(long time) {
|
||||
return (
|
||||
(Math.round((time / 3600.0) * 100d)) / 100d + TimeConstants.getHours()
|
||||
);
|
||||
boolean round = TimeConstants.getRounded();
|
||||
double hours = time / 3600.0;
|
||||
|
||||
if (round) {
|
||||
int roundedHours = (int) Math.round(hours);
|
||||
return roundedHours + TimeConstants.getHours();
|
||||
}
|
||||
|
||||
hours = (Math.round(hours * 100d)) / 100d;
|
||||
return hours + TimeConstants.getHours();
|
||||
}
|
||||
}
|
||||
@@ -17,19 +17,25 @@ public class ChatUtil {
|
||||
|
||||
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")
|
||||
)
|
||||
);
|
||||
case NO_PERMISSION:
|
||||
sender.sendMessage(
|
||||
format(DATA_MANAGER.getConfig().getString("messages.noPermission"))
|
||||
);
|
||||
break;
|
||||
case PLAYER_NOT_FOUND:
|
||||
sender.sendMessage(
|
||||
formatWithPrefix(
|
||||
DATA_MANAGER.getConfig().getString("messages.player-not-found")
|
||||
)
|
||||
);
|
||||
break;
|
||||
case PLAYER_NEVER_PLAYED:
|
||||
sender.sendMessage(
|
||||
formatWithPrefix(
|
||||
DATA_MANAGER.getConfig().getString("messages.player-never-joined")
|
||||
)
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,25 +10,28 @@ public class HexUtil {
|
||||
|
||||
public static String hex(String message) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
int index = 0;
|
||||
int length = message.length();
|
||||
|
||||
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;
|
||||
for (int i = 0; i < length; i++) {
|
||||
if (
|
||||
message.charAt(i) == '<' &&
|
||||
i + 8 < length &&
|
||||
message.charAt(i + 1) == '#'
|
||||
) {
|
||||
String hexCode = message.substring(i + 2, i + 8);
|
||||
if (message.charAt(i + 8) == '>' && isValidHexCode(hexCode)) {
|
||||
builder.append(ChatColor.of('#' + hexCode));
|
||||
i += 8; // Skip the processed hex code and the '>'
|
||||
continue;
|
||||
}
|
||||
}
|
||||
builder.append(message.substring(index));
|
||||
break;
|
||||
builder.append(message.charAt(i));
|
||||
}
|
||||
|
||||
return ChatColor.translateAlternateColorCodes('&', builder.toString());
|
||||
}
|
||||
|
||||
private static boolean isValidHexCode(String hexCode) {
|
||||
return hexCode.matches("^[a-fA-F0-9]{6}$");
|
||||
}
|
||||
}
|
||||
@@ -36,16 +36,36 @@ public class ServerUtils {
|
||||
* @return true if so
|
||||
*/
|
||||
public static boolean isRisenVersion() {
|
||||
String[] versionParts = Bukkit.getServer().getVersion().split("\\.");
|
||||
String version = Bukkit.getServer().getVersion();
|
||||
String mcVersion = null;
|
||||
|
||||
int majorVersion = Integer.parseInt(
|
||||
versionParts[1].replaceAll("[^0-9]", "")
|
||||
);
|
||||
int minorVersion = 0;
|
||||
if (versionParts.length >= 3) minorVersion =
|
||||
Integer.parseInt(versionParts[2].replaceAll("[^0-9]", ""));
|
||||
if (version.contains("(MC:")) {
|
||||
int startIndex = version.indexOf("(MC:") + 5;
|
||||
int endIndex = version.indexOf(")", startIndex);
|
||||
mcVersion = version.substring(startIndex, endIndex).trim();
|
||||
}
|
||||
|
||||
return majorVersion >= 17 && minorVersion >= 0;
|
||||
if (mcVersion == null) {
|
||||
Bukkit
|
||||
.getLogger()
|
||||
.warning("PlayTimes failed to extract Minecraft version: " + version);
|
||||
return false;
|
||||
}
|
||||
|
||||
String[] versionParts = mcVersion.split("\\.");
|
||||
|
||||
try {
|
||||
int minorVersion = versionParts.length >= 2
|
||||
? Integer.parseInt(versionParts[1])
|
||||
: 0;
|
||||
|
||||
return minorVersion >= 17;
|
||||
} catch (NumberFormatException e) {
|
||||
Bukkit
|
||||
.getLogger()
|
||||
.warning("PlayTimes failed to parse Minecraft version: " + mcVersion);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean hasPAPI() {
|
||||
|
||||
@@ -1,27 +1,26 @@
|
||||
# PlayTimes by CodedRed
|
||||
# For support please ask here: https://github.com/CodedRed-Spigot/PlayTimes/issues
|
||||
# For assistance, please submit inquiries here: https://github.com/CodedRed-Spigot/PlayTimes/issues
|
||||
|
||||
# Prefix will show before 'player-not-found' & 'player-never-joined' messages
|
||||
# The 'prefix' configures the introductory text for 'player-not-found' and 'player-never-joined' notifications.
|
||||
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
|
||||
# Placeholder API Configuration
|
||||
# Activate this only if using PlaceholderAPI with PlayTimes.
|
||||
# To integrate PlayTimes placeholders into other plugins, simply install PlaceholderAPI; integration occurs seamlessly.
|
||||
use-papi-placeholders: false
|
||||
|
||||
# PlayTimes format & message settings
|
||||
# The name refers to the format. See spigot plugin page for format examples
|
||||
# PlayTimes Formatting and Message Customization
|
||||
# 'playtime.name' defines time unit labels. For formatting guidance, refer to our Spigot plugin page.
|
||||
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
|
||||
## Default Placeholders:
|
||||
## %player%, %playtime%, %timesjoined%, %joindate%, %rawTime%, %afkTime%
|
||||
## For database placeholders, visit: https://github.com/CodedRed-Spigot/PlayTimes/wiki/Bungee-Support
|
||||
## PlaceholderAPI placeholders are also compatible.
|
||||
message:
|
||||
- "&b&m=======&b&l[%player%]&b&m======="
|
||||
- "&aPlaytime:&f %time%"
|
||||
- "&aTimes joined:&f %timesjoined%"
|
||||
- "&aJoined Date:&f %joindate%"
|
||||
- "&aPlaytime:&f %playtime%"
|
||||
- "&aTimes Joined:&f %timesjoined%"
|
||||
- "&aJoin Date:&f %joindate%"
|
||||
- "&b&m============================"
|
||||
name:
|
||||
second: "s"
|
||||
@@ -33,52 +32,71 @@ playtime:
|
||||
hours: "hrs "
|
||||
days: "days "
|
||||
|
||||
## only-hours - when true it will display playtime in hours (When true this will also disable show-seconds/days setting)
|
||||
## show-seconds - when true it will display seconds
|
||||
## show-days - when true it will display days
|
||||
## 'only-hours' - Displays playtime solely in hours. Activating this overrides 'show-seconds' and 'show-days'.
|
||||
## 'show-seconds' - Includes seconds in the display.
|
||||
## 'show-days' - Includes days in the display.
|
||||
only-hours: false
|
||||
show-seconds: true
|
||||
show-days: true
|
||||
## 'round-numbers' - Rounds off the playtime to whole numbers when 'only-hours' is true.
|
||||
round-numbers: true
|
||||
|
||||
# /Uptime command info - only placeholder is %serveruptime%
|
||||
# AFK Tracker Configuration
|
||||
# NOTE: When enabled, this will remove afk time from %playtime% placeholder
|
||||
afk-settings:
|
||||
enabled: true
|
||||
|
||||
## Time in minutes after which a player is considered AFK.
|
||||
threshold: 5
|
||||
|
||||
## Notifications settings for AFK status changes.
|
||||
broadcast-afk:
|
||||
on-enter-afk: true
|
||||
on-exit-afk: true
|
||||
|
||||
# Message to send to the player when they are marked as AFK.
|
||||
on-enter-afk-message: "&eYou are now marked as AFK."
|
||||
# Message to send to the player when they are no longer marked as AFK.
|
||||
on-exit-afk-message: "&eYou are no longer AFK."
|
||||
# Leave true unless you are experiencing lag/issues with one of the afk listeners.
|
||||
cancel-afk:
|
||||
on-player-move: true
|
||||
on-player-chat: true
|
||||
on-player-interact: true
|
||||
|
||||
# /Uptime Command Configuration - Use '%serveruptime%' to display server uptime.
|
||||
uptime:
|
||||
message:
|
||||
- "&b&m============================"
|
||||
- "&aServer Uptime:&f %serveruptime%"
|
||||
- "&b&m============================"
|
||||
|
||||
# /toppt command info
|
||||
## Built-in Placeholders:
|
||||
## %player% %place% %time% %joindate%
|
||||
## You may also use PAPI placeholders
|
||||
# /toppt Command Settings
|
||||
## Standard Placeholders:
|
||||
## %player%, %place%, %time%, %joindate%
|
||||
## PlaceholderAPI placeholders are also supported.
|
||||
top-playtime:
|
||||
header: "&b******&9[&3&lPlayTime Leaderboards&9]&b*****"
|
||||
content: "&5%place%) &9&l%player% &9&o- %time%"
|
||||
footer: "&b****************************************"
|
||||
enable-cooldown: true
|
||||
cooldown-seconds: 60
|
||||
track-rawtime: false
|
||||
|
||||
# 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' - Customize this to change the format of join dates.
|
||||
# Explore more formatting options at: https://docs.oracle.com/javase/8/docs/api/java/text/SimpleDateFormat.html
|
||||
date-format: "MM/dd/yyyy"
|
||||
|
||||
# Built in messages, may change to your liking :D
|
||||
# Customizable Built-In Messages
|
||||
messages:
|
||||
noPermission: "&cYou cannot run this command."
|
||||
player-not-found: "&cPlayer not found."
|
||||
player-never-joined: "&cPlayer has never joined the server!"
|
||||
cooldown: "&cYou cannot use this command for %timeleft% seconds!"
|
||||
player-not-found: "&cUnable to locate player."
|
||||
player-never-joined: "&cThis player has not joined the server."
|
||||
cooldown: "&cCommand unavailable 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============================"
|
||||
# Do not change this unless you know what you're doing!
|
||||
# This setting is for servers experiencing issues when looking up offline players.
|
||||
# For more information, see the link below.
|
||||
uuid-lookups:
|
||||
what-does-this-do: https://github.com/CodedRed-Spigot/PlayTimes/wiki/UUID-LOOKUPS
|
||||
type: "default"
|
||||
@@ -0,0 +1 @@
|
||||
# DO NOT ALTER THIS FILE.
|
||||
@@ -10,7 +10,7 @@ database-settings:
|
||||
# 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 'serverId' will also be used for placeholders, like %playtime_serverId% (e.g., %playtime_survival%).
|
||||
# The placeholder will return the playtime on that specific server.
|
||||
serverId: "survival"
|
||||
|
||||
@@ -19,3 +19,12 @@ database-settings:
|
||||
purge-database:
|
||||
enabled: false
|
||||
months: 12
|
||||
# Placeholders:
|
||||
## For use in Plugin:
|
||||
# %rawtime_serverId%
|
||||
# %afktime_serverId%
|
||||
# %playtime_serverId%
|
||||
## For PAPI:
|
||||
# %PlayTimes_rawtime_serverId%
|
||||
# %PlayTimes_afktime_serverId%
|
||||
# %PlayTimes_playtime_serverId%
|
||||
@@ -0,0 +1,89 @@
|
||||
# PlayTimes by CodedRed
|
||||
# For assistance, please submit inquiries here: https://github.com/CodedRed-Spigot/PlayTimes/issues
|
||||
|
||||
# The 'prefix' configures the introductory text for 'player-not-found' and 'player-never-joined' notifications.
|
||||
prefix: "&7[&b&lPlayTimes&7]"
|
||||
|
||||
# Placeholder API Configuration
|
||||
# Activate this only if using PlaceholderAPI with PlayTimes.
|
||||
# To integrate PlayTimes placeholders into other plugins, simply install PlaceholderAPI; integration occurs seamlessly.
|
||||
use-papi-placeholders: false
|
||||
|
||||
# PlayTimes Formatting and Message Customization
|
||||
# 'playtime.name' defines time unit labels. For formatting guidance, refer to our Spigot plugin page.
|
||||
playtime:
|
||||
## Default Placeholders:
|
||||
## %player%, %playtime%, %timesjoined%, %joindate%, %rawTime%, %afkTime%
|
||||
## For database placeholders, visit: https://github.com/CodedRed-Spigot/PlayTimes/wiki/Bungee-Support
|
||||
## PlaceholderAPI placeholders are also compatible.
|
||||
message:
|
||||
- "&b&m=======&b&l[%player%]&b&m======="
|
||||
- "&aPlaytime:&f %playtime%"
|
||||
- "&aTimes Joined:&f %timesjoined%"
|
||||
- "&aJoin Date:&f %joindate%"
|
||||
- "&b&m============================"
|
||||
name:
|
||||
second: "s"
|
||||
minute: "min "
|
||||
hour: "hr "
|
||||
day: "day "
|
||||
seconds: "s"
|
||||
minutes: "mins "
|
||||
hours: "hrs "
|
||||
days: "days "
|
||||
|
||||
## 'only-hours' - Displays playtime solely in hours. Activating this overrides 'show-seconds' and 'show-days'.
|
||||
## 'show-seconds' - Includes seconds in the display.
|
||||
## 'show-days' - Includes days in the display.
|
||||
only-hours: false
|
||||
show-seconds: true
|
||||
show-days: true
|
||||
## 'round-numbers' - Rounds off the playtime to whole numbers when 'only-hours' is true.
|
||||
round-numbers: true
|
||||
|
||||
# AFK Tracker Configuration
|
||||
# NOTE: When enabled, this will remove afk time from %time% placeholder
|
||||
afk-settings:
|
||||
enabled: true
|
||||
|
||||
## Time in minutes after which a player is considered AFK.
|
||||
threshold: 2
|
||||
|
||||
## Notifications settings for AFK status changes.
|
||||
notify-on-afk:
|
||||
onAFK: true
|
||||
onBackFromAFK: true
|
||||
|
||||
# Message to send to the player when they are marked as AFK.
|
||||
afk-message: "&eYou are now marked as AFK."
|
||||
# Message to send to the player when they are no longer marked as AFK.
|
||||
back-from-afk-message: "&eYou are no longer AFK."
|
||||
|
||||
# /Uptime Command Configuration - Use '%serveruptime%' to display server uptime.
|
||||
uptime:
|
||||
message:
|
||||
- "&b&m============================"
|
||||
- "&aServer Uptime:&f %serveruptime%"
|
||||
- "&b&m============================"
|
||||
|
||||
# /toppt Command Settings
|
||||
## Standard Placeholders:
|
||||
## %player%, %place%, %time%, %joindate%
|
||||
## PlaceholderAPI placeholders are also supported.
|
||||
top-playtime:
|
||||
header: "&b******&9[&3&lPlayTime Leaderboards&9]&b*****"
|
||||
content: "&5%place%) &9&l%player% &9&o- %time%"
|
||||
footer: "&b****************************************"
|
||||
enable-cooldown: true
|
||||
cooldown-seconds: 60
|
||||
|
||||
# 'date-format' - Customize this to change the format of join dates.
|
||||
# Explore more formatting options at: https://docs.oracle.com/javase/8/docs/api/java/text/SimpleDateFormat.html
|
||||
date-format: "MM/dd/yyyy"
|
||||
|
||||
# Customizable Built-In Messages
|
||||
messages:
|
||||
noPermission: "&cYou cannot run this command."
|
||||
player-not-found: "&cUnable to locate player."
|
||||
player-never-joined: "&cThis player has not joined the server."
|
||||
cooldown: "&cCommand unavailable for %timeleft% seconds!"
|
||||
@@ -1,24 +1,21 @@
|
||||
name: Playtimes
|
||||
version: "${version}"
|
||||
main: me.codedred.playtimes.PlayTimes
|
||||
# Keeping 'Cmaaxx' as author for Metric purposes.
|
||||
author: Cmaaxx
|
||||
authors: [CodedRed]
|
||||
version: '${version}'
|
||||
softdepend: [PlaceholderAPI]
|
||||
description: Check Players PlayTime And More!
|
||||
|
||||
commands:
|
||||
playtime:
|
||||
description: Check your playtime!
|
||||
usage: /playtime
|
||||
permission: pt.use
|
||||
aliases: [playt, playerinfo, pt]
|
||||
description: "Check your playtime!"
|
||||
usage: "/playtime"
|
||||
uptime:
|
||||
description: Check your servers uptime!
|
||||
usage: /uptime
|
||||
permission: pt.uptime
|
||||
aliases: [serveruptime, serverupt]
|
||||
description: "Check your servers uptime!"
|
||||
usage: "/uptime"
|
||||
topplaytime:
|
||||
description: Check your servers uptime!
|
||||
usage: /topplaytime
|
||||
permission: pt.top
|
||||
aliases: [topplayt, toppt]
|
||||
aliases: [topplayt, toppt]
|
||||
description: "Check your servers uptime!"
|
||||
usage: "/topplaytime"
|
||||
Reference in new issue
Block a user