aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLMBishop <13875753+LMBishop@users.noreply.github.com>2022-06-26 00:26:27 +0100
committerLMBishop <13875753+LMBishop@users.noreply.github.com>2022-06-26 00:26:27 +0100
commit2fa380b2c9d81b539daffc8d5608fb9287ed63a6 (patch)
treefae2c756c2409f6af6d0a6e3b30975d425b57688
parent4cf5e7550b928b6204484813c9bcf843ef29dced (diff)
Add quests debug command
-rw-r--r--bukkit/src/main/java/com/leonardobishop/quests/bukkit/BukkitQuestsLogger.java17
-rw-r--r--bukkit/src/main/java/com/leonardobishop/quests/bukkit/BukkitQuestsPlugin.java7
-rw-r--r--bukkit/src/main/java/com/leonardobishop/quests/bukkit/command/AdminCommandSwitcher.java2
-rw-r--r--bukkit/src/main/java/com/leonardobishop/quests/bukkit/command/AdminDebugCommandHandler.java334
-rw-r--r--bukkit/src/main/java/com/leonardobishop/quests/bukkit/questcompleter/BukkitQuestCompleter.java23
-rw-r--r--bukkit/src/main/java/com/leonardobishop/quests/bukkit/util/LogHistory.java71
-rw-r--r--common/src/main/java/com/leonardobishop/quests/common/player/QPlayerManager.java12
7 files changed, 441 insertions, 25 deletions
diff --git a/bukkit/src/main/java/com/leonardobishop/quests/bukkit/BukkitQuestsLogger.java b/bukkit/src/main/java/com/leonardobishop/quests/bukkit/BukkitQuestsLogger.java
index d50752fd..da8c791c 100644
--- a/bukkit/src/main/java/com/leonardobishop/quests/bukkit/BukkitQuestsLogger.java
+++ b/bukkit/src/main/java/com/leonardobishop/quests/bukkit/BukkitQuestsLogger.java
@@ -24,22 +24,15 @@ public class BukkitQuestsLogger implements QuestsLogger {
@Override
public void log(String str, LoggingLevel level) {
+ plugin.getLogHistory().record(level, () -> str);
if (serverLoggingLevel.getNumericVerbosity() < level.getNumericVerbosity()) {
return;
}
switch (level) {
- case DEBUG:
- plugin.getLogger().info("Debug: " + str);
- break;
- case INFO:
- plugin.getLogger().info(str);
- break;
- case ERROR:
- plugin.getLogger().severe(str);
- break;
- case WARNING:
- plugin.getLogger().warning(str);
- break;
+ case DEBUG -> plugin.getLogger().info("DEBUG: " + str);
+ case INFO -> plugin.getLogger().info(str);
+ case ERROR -> plugin.getLogger().severe(str);
+ case WARNING -> plugin.getLogger().warning(str);
}
}
diff --git a/bukkit/src/main/java/com/leonardobishop/quests/bukkit/BukkitQuestsPlugin.java b/bukkit/src/main/java/com/leonardobishop/quests/bukkit/BukkitQuestsPlugin.java
index c6e3e260..2006f609 100644
--- a/bukkit/src/main/java/com/leonardobishop/quests/bukkit/BukkitQuestsPlugin.java
+++ b/bukkit/src/main/java/com/leonardobishop/quests/bukkit/BukkitQuestsPlugin.java
@@ -33,6 +33,7 @@ import com.leonardobishop.quests.bukkit.storage.YamlStorageProvider;
import com.leonardobishop.quests.bukkit.tasktype.BukkitTaskTypeManager;
import com.leonardobishop.quests.bukkit.tasktype.type.*;
import com.leonardobishop.quests.bukkit.tasktype.type.dependent.*;
+import com.leonardobishop.quests.bukkit.util.LogHistory;
import com.leonardobishop.quests.common.config.ConfigProblem;
import com.leonardobishop.quests.common.config.ConfigProblemDescriptions;
import com.leonardobishop.quests.common.config.QuestsConfig;
@@ -92,6 +93,7 @@ public class BukkitQuestsPlugin extends JavaPlugin implements Quests {
private Title titleHandle;
private VersionSpecificHandler versionSpecificHandler;
+ private LogHistory logHistory;
private BukkitTask questAutoSaveTask;
private BukkitTask questQueuePollTask;
private BiFunction<Player, String, String> placeholderAPIProcessor;
@@ -150,6 +152,7 @@ public class BukkitQuestsPlugin extends JavaPlugin implements Quests {
public void onEnable() {
// Initial module initialization
this.questsLogger = new BukkitQuestsLogger(this);
+ this.logHistory = new LogHistory(true);
this.generateConfigurations();
this.questsConfig = new BukkitQuestsConfig(new File(super.getDataFolder() + File.separator + "config.yml"));
this.questManager = new QuestManager(this);
@@ -602,6 +605,10 @@ public class BukkitQuestsPlugin extends JavaPlugin implements Quests {
return questsConfig.getConfig();
}
+ public LogHistory getLogHistory() {
+ return logHistory;
+ }
+
@Override
public void reloadConfig() {
this.reloadBaseConfiguration();
diff --git a/bukkit/src/main/java/com/leonardobishop/quests/bukkit/command/AdminCommandSwitcher.java b/bukkit/src/main/java/com/leonardobishop/quests/bukkit/command/AdminCommandSwitcher.java
index be86e6df..797ebcd7 100644
--- a/bukkit/src/main/java/com/leonardobishop/quests/bukkit/command/AdminCommandSwitcher.java
+++ b/bukkit/src/main/java/com/leonardobishop/quests/bukkit/command/AdminCommandSwitcher.java
@@ -24,6 +24,7 @@ public class AdminCommandSwitcher extends CommandSwitcher {
super.subcommands.put("update", new AdminUpdateCommandHandler(plugin));
super.subcommands.put("wiki", new AdminWikiCommandHandler(plugin));
super.subcommands.put("about", new AdminAboutCommandHandler(plugin));
+ super.subcommands.put("debug", new AdminDebugCommandHandler(plugin));
}
@Override
@@ -42,6 +43,7 @@ public class AdminCommandSwitcher extends CommandSwitcher {
sender.sendMessage(ChatColor.DARK_GRAY + " * " + ChatColor.RED + "/quests a update " + ChatColor.DARK_GRAY + ": check for updates");
sender.sendMessage(ChatColor.DARK_GRAY + " * " + ChatColor.RED + "/quests a wiki " + ChatColor.DARK_GRAY + ": get a link to the Quests wiki");
sender.sendMessage(ChatColor.DARK_GRAY + " * " + ChatColor.RED + "/quests a about " + ChatColor.DARK_GRAY + ": get information about Quests");
+ sender.sendMessage(ChatColor.DARK_GRAY + " * " + ChatColor.RED + "/quests a debug " + ChatColor.DARK_GRAY + ": generate a debug report");
}
@Override
diff --git a/bukkit/src/main/java/com/leonardobishop/quests/bukkit/command/AdminDebugCommandHandler.java b/bukkit/src/main/java/com/leonardobishop/quests/bukkit/command/AdminDebugCommandHandler.java
new file mode 100644
index 00000000..9e222327
--- /dev/null
+++ b/bukkit/src/main/java/com/leonardobishop/quests/bukkit/command/AdminDebugCommandHandler.java
@@ -0,0 +1,334 @@
+package com.leonardobishop.quests.bukkit.command;
+
+import com.leonardobishop.quests.bukkit.BukkitQuestsPlugin;
+import com.leonardobishop.quests.bukkit.item.QuestItem;
+import com.leonardobishop.quests.bukkit.questcompleter.BukkitQuestCompleter;
+import com.leonardobishop.quests.bukkit.util.LogHistory;
+import com.leonardobishop.quests.common.player.QPlayer;
+import com.leonardobishop.quests.common.player.QPlayerPreferences;
+import com.leonardobishop.quests.common.player.questprogressfile.QuestProgress;
+import com.leonardobishop.quests.common.player.questprogressfile.QuestProgressFile;
+import com.leonardobishop.quests.common.player.questprogressfile.TaskProgress;
+import com.leonardobishop.quests.common.quest.Category;
+import com.leonardobishop.quests.common.quest.Quest;
+import com.leonardobishop.quests.common.quest.Task;
+import com.leonardobishop.quests.common.tasktype.TaskType;
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.FileAlreadyExistsException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.attribute.FileAttribute;
+import java.util.*;
+import java.util.function.Function;
+
+public class AdminDebugCommandHandler implements CommandHandler {
+
+ private final BukkitQuestsPlugin plugin;
+
+ private List<String> errors;
+ private CommandSender currentReportGenerator;
+
+ public AdminDebugCommandHandler(BukkitQuestsPlugin plugin) {
+ this.plugin = plugin;
+ }
+
+ @Override
+ public void handle(CommandSender sender, String[] args) {
+ if (currentReportGenerator != null) {
+ sender.sendMessage(ChatColor.RED + "A report is already being generated. Please wait until it is finished.");
+ return;
+ }
+
+ errors = new ArrayList<>();
+ currentReportGenerator = sender;
+
+ try {
+ sender.sendMessage(ChatColor.GRAY + "Generating Quests debug report...");
+ if (!plugin.getLogHistory().isEnabled()) {
+ sender.sendMessage(ChatColor.RED + "Log history is not enabled. Quests will only generate a basic debug report. " +
+ "If you were asked to generate one with log history, this must be turned on in your configuration.");
+ }
+ long start = System.currentTimeMillis();
+ Path path = new File(plugin.getDataFolder() + File.separator + "debug" + File.separator + "debug_" + start + ".txt").toPath();
+ try {
+ Path directory = new File(plugin.getDataFolder() + File.separator + "debug").toPath();
+ Files.createDirectories(directory);
+ Files.createFile(path);
+ } catch (IOException e) {
+ sender.sendMessage(ChatColor.DARK_RED + "Failed to create debug file!");
+ e.printStackTrace();
+ return;
+ }
+
+ List<String> lines = new ArrayList<>();
+ lines.add("################################");
+ lines.add("# Server Information #");
+ lines.add("################################");
+ lines.add("");
+ lines.add("Server name: " + plugin.getServer().getName());
+ lines.add("Server version: " + plugin.getServer().getVersion());
+ lines.add("Bukkit version: " + plugin.getServer().getBukkitVersion());
+ lines.add("Minecraft version: " + plugin.getServer().getMinecraftVersion());
+ lines.add("Player count: " + plugin.getServer().getOnlinePlayers().size());
+ lines.add("");
+
+ lines.add("################################");
+ lines.add("# Quests Information #");
+ lines.add("################################");
+ lines.add("");
+ lines.add("Quests version: " + plugin.getDescription().getVersion());
+ lines.add("");
+ printList(lines, 0, "Task types available", plugin.getTaskTypeManager().getTaskTypes(), TaskType::getType);
+ lines.add("");
+ printList(lines, 0, "Quests", plugin.getQuestManager().getQuests().values(), Quest::getId);
+ lines.add("");
+ printList(lines, 0, "Categories", plugin.getQuestManager().getCategories(), Category::getId);
+ lines.add("");
+ BukkitQuestCompleter completer = (BukkitQuestCompleter) plugin.getQuestCompleter();
+ printList(lines, 0, "Completion queue", completer.getCompletionQueue(), questProgress -> questProgress.getPlayer().toString());
+ lines.add("");
+ printList(lines, 0, "Full check queue", completer.getFullCheckQueue(), questProgressFile -> questProgressFile.getPlayerUUID().toString());
+ lines.add("");
+ printList(lines, 0, "Expired check queue", completer.getExpiredCheckQueue(), UUID::toString);
+ lines.add("");
+
+ lines.add("################################");
+ lines.add("# Storage #");
+ lines.add("################################");
+ lines.add("");
+ lines.add("Storage provider: " + plugin.getStorageProvider().getName());
+ lines.add("");
+
+ lines.add("################################");
+ lines.add("# Hook #");
+ lines.add("################################");
+ lines.add("");
+ lines.add("Core protect hook: " + (plugin.getCoreProtectHook() != null));
+ lines.add("Essentials hook: " + (plugin.getEssentialsHook() != null));
+ lines.add("PlaceholderAPI hook: " + (plugin.getPlaceholderAPIHook() != null));
+ lines.add("Item getter: " + plugin.getItemGetter().getClass().getSimpleName());
+ lines.add("Title handler: " + plugin.getTitleHandle().getClass().getSimpleName());
+ lines.add("Version specific handler: " + plugin.getVersionSpecificHandler().getClass().getSimpleName());
+ lines.add("");
+
+ lines.add("################################");
+ lines.add("# Items #");
+ lines.add("################################");
+ lines.add("");
+ lines.add("Number of items: " + plugin.getQuestItemRegistry().getAllItems().size());
+ lines.add("");
+ //TODO this
+
+ lines.add("################################");
+ lines.add("# Quests #");
+ lines.add("################################");
+ lines.add("");
+ lines.add("Number of quests: " + plugin.getQuestManager().getQuests().size());
+ lines.add("");
+ for (Quest quest : plugin.getQuestManager().getQuests().values()) {
+ Map<String, Object> questValues = getFieldValues(quest, "tasks", "tasksByType");
+ try {
+ Field tasksField = quest.getClass().getDeclaredField("tasks");
+ tasksField.setAccessible(true);
+ Map<String, Task> tasksMap = (Map<String, Task>) tasksField.get(quest);
+ Map<String, Object> tasksValues = new HashMap<>();
+ for (Map.Entry<String, Task> taskEntry : tasksMap.entrySet()) {
+ Task task = taskEntry.getValue();
+ tasksValues.put(task.getId(), getFieldValues(task));
+ }
+ questValues.put("tasks", tasksValues);
+ } catch (NoSuchFieldException | IllegalAccessException e) {
+ error("Failed to get tasks for quest " + quest.getId() + ": " + e.getClass().getSimpleName() + "(" + e.getMessage() + ")");
+ e.printStackTrace();
+ }
+
+ printMap(lines, 0, "Quest '" + quest.getId() + "'", questValues);
+ lines.add("");
+ }
+
+ lines.add("################################");
+ lines.add("# Players #");
+ lines.add("################################");
+ lines.add("");
+ printList(lines, 0, "Players online", Bukkit.getOnlinePlayers(), player -> player.getUniqueId().toString());
+ lines.add("");
+ printList(lines, 0, "QPlayers loaded", plugin.getPlayerManager().getQPlayers(), qPlayer -> qPlayer.getPlayerUUID().toString());
+ lines.add("");
+ for (QPlayer qPlayer : plugin.getPlayerManager().getQPlayers()) {
+ lines.add("QPlayer " + qPlayer.getPlayerUUID() + ":");
+ QPlayerPreferences preferences = qPlayer.getPlayerPreferences();
+ printMap(lines, 1, "Preferences", getFieldValues(preferences));
+
+ QuestProgressFile questProgressFile = qPlayer.getQuestProgressFile();
+ try {
+ Field questProgressField = questProgressFile.getClass().getDeclaredField("questProgress");
+ questProgressField.setAccessible(true);
+ Map<String, QuestProgress> questProgressMap = (Map<String, QuestProgress>) questProgressField.get(questProgressFile);
+ Map<String, Object> questProgressValues = new LinkedHashMap<>();
+ for (Map.Entry<String, QuestProgress> entry : questProgressMap.entrySet()) {
+ QuestProgress questProgress = entry.getValue();
+ Map<String, Object> questProgressValue = getFieldValues(questProgress, "plugin", "taskProgress");
+
+ Field taskProgressField = questProgress.getClass().getDeclaredField("taskProgress");
+ taskProgressField.setAccessible(true);
+ Map<String, TaskProgress> taskProgressMap = (Map<String, TaskProgress>) taskProgressField.get(questProgress);
+ Map<String, Object> taskProgressValues = new LinkedHashMap<>();
+ for (Map.Entry<String, TaskProgress> taskEntry : taskProgressMap.entrySet()) {
+ TaskProgress taskProgress = taskEntry.getValue();
+ taskProgressValues.put(taskEntry.getKey(), getFieldValues(taskProgress, "plugin", "linkedQuestProgress"));
+ }
+ questProgressValue.put("taskProgress", taskProgressValues);
+
+ questProgressValues.put(entry.getKey(), questProgressValue);
+ }
+ printMap(lines, 1, "Quest progress", questProgressValues);
+ } catch (NoSuchFieldException | IllegalAccessException e) {
+ error("Failed to get quest progress for QPlayer " + qPlayer.getPlayerUUID() + ": " + e.getClass().getSimpleName() + "(" + e.getMessage() + ")");
+ e.printStackTrace();
+ }
+ lines.add(" Quest controller: " + qPlayer.getQuestController().getName());
+ lines.add("");
+ }
+
+ lines.add("################################");
+ lines.add("# Log History #");
+ lines.add("################################");
+ lines.add("");
+ for (LogHistory.LogEntry line : plugin.getLogHistory().getEntries()) {
+ lines.add(String.format("[%s/%s/%s] %s", line.getTime(), line.getType().toString(), line.getThread(), line.getEntry()));
+ }
+
+ List<String> errors = new ArrayList<>();
+ lines.add(0, "");
+ printList(errors, 0, "Errors generating report", this.errors, String::valueOf);
+ lines.addAll(0, errors);
+ lines.add(0, "Time taken: " + (System.currentTimeMillis() - start) + "ms");
+ lines.add(0, "Generated at: " + new Date(start) + " (" + start + ")");
+ lines.add(0, "");
+ lines.add(0, "################################");
+ lines.add(0, "# Report Information #");
+ lines.add(0, "################################");
+ try {
+ Files.write(path, lines, StandardCharsets.UTF_8);
+ } catch (IOException e) {
+ error("Failed to write report to " + path + "!");
+ e.printStackTrace();
+ return;
+ }
+
+ sender.sendMessage(ChatColor.GREEN + "Debug file created at " + path + ". (Took " + (System.currentTimeMillis() - start) + "ms.)");
+ } finally {
+ currentReportGenerator = null;
+ errors = new ArrayList<>();
+ }
+ }
+
+ private Map<String, Object> getFieldValues(Object object, String... excludeFields) {
+ Field[] fields = object.getClass().getDeclaredFields();
+ Map<String, Object> values = new LinkedHashMap<>();
+ for (Field field : fields) {
+ if (Arrays.asList(excludeFields).contains(field.getName())) {
+ continue;
+ }
+ field.setAccessible(true);
+ try {
+ values.put(field.getName(), field.get(object));
+ } catch (IllegalAccessException e) {
+ error("Failed to get field value for " + object.getClass().getSimpleName() + "." + field.getName() + ": " + e.getClass().getSimpleName() + "(" + e.getMessage() + ")");
+ e.printStackTrace();
+ }
+ }
+ return values;
+ }
+
+ private <E> void printList(List<String> lines, int depth, String title, Collection<E> list) {
+ printList(lines, depth, title, list, Object::toString);
+ }
+
+ private <E> void printList(List<String> lines, int depth, String title, Collection<E> list, Function<E, String> getter) {
+ depth = depth * 4;
+ if (list.size() == 0) {
+ lines.add(String.format("%s%s (0): (empty)", " ".repeat(depth), title));
+ return;
+ }
+ lines.add(String.format("%s%s (%d):", " ".repeat(depth), title, list.size()));
+ for (E element : list) {
+ lines.add(String.format("%s - %s", " ".repeat(depth), getter.apply(element)));
+ }
+ }
+
+ private <K, V> void printMap(List<String> lines, int depth, String title, Map<K, V> map) {
+ depth = depth * 4;
+ if (map.size() == 0) {
+ lines.add(String.format("%s%s (0): (empty)", " ".repeat(depth), title));
+ return;
+ }
+ lines.add(String.format("%s%s:", " ".repeat(depth), title));
+ int keyMaxLength = 1;
+ int valueMaxLength = 1;
+ Map<String, String> stringifiedValues = new HashMap<>();
+ for (Map.Entry<K, V> entry : map.entrySet()) {
+ String key = String.valueOf(entry.getKey());
+ if (key.length() > keyMaxLength) {
+ keyMaxLength = key.length();
+ }
+ }
+ for (Map.Entry<K, V> entry : map.entrySet()) {
+ String value;
+ if (entry.getValue() instanceof Map) {
+ List<String> subLines = new ArrayList<>();
+ printMap(subLines, 0, "Map", (Map<?, ?>) entry.getValue());
+ value = String.join("\n", subLines);
+ } else if (entry.getValue() instanceof List) {
+ List<String> subLines = new ArrayList<>();
+ printList(subLines, 0, "List", (Collection<?>) entry.getValue());
+ value = String.join("\n", subLines);
+ } else {
+ value = String.valueOf(entry.getValue());
+ }
+
+ for (String line : value.split("\n")) {
+ if (line.length() > valueMaxLength) {
+ valueMaxLength = line.length();
+ }
+ }
+ stringifiedValues.put(String.valueOf(entry.getKey()), value);
+ }
+ String separator = String.format("%s|-%-" + keyMaxLength + "s-+-%-" + valueMaxLength + "s-|", " ".repeat(depth), "-".repeat(keyMaxLength), "-".repeat(valueMaxLength));
+ lines.add(separator);
+ for (Map.Entry<String, String> entry : stringifiedValues.entrySet()) {
+ String value = entry.getValue();
+ boolean firstLine = true;
+ for (String line : value.split("\n")) {
+ lines.add(String.format("%s| %-" + keyMaxLength + "s | %-" + valueMaxLength + "s |", " ".repeat(depth), firstLine ? entry.getKey() : "", line));
+ firstLine = false;
+ }
+ lines.add(separator);
+ }
+ }
+
+ private void error(String error) {
+ errors.add(error);
+ currentReportGenerator.sendMessage(ChatColor.RED + error);
+ }
+
+ @Override
+ public List<String> tabComplete(CommandSender sender, String[] args) {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public @Nullable String getPermission() {
+ return "quests.admin";
+ }
+}
diff --git a/bukkit/src/main/java/com/leonardobishop/quests/bukkit/questcompleter/BukkitQuestCompleter.java b/bukkit/src/main/java/com/leonardobishop/quests/bukkit/questcompleter/BukkitQuestCompleter.java
index 12342bd2..bf264a69 100644
--- a/bukkit/src/main/java/com/leonardobishop/quests/bukkit/questcompleter/BukkitQuestCompleter.java
+++ b/bukkit/src/main/java/com/leonardobishop/quests/bukkit/questcompleter/BukkitQuestCompleter.java
@@ -13,17 +13,14 @@ import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
-import java.util.LinkedList;
-import java.util.Objects;
-import java.util.Queue;
-import java.util.UUID;
+import java.util.*;
//TODO move complete effects here ?
public class BukkitQuestCompleter implements QuestCompleter, Runnable {
- private final Queue<QuestProgress> completionQueue = new LinkedList<>();
- private final Queue<QuestProgressFile> fullCheckQueue = new LinkedList<>();
- private final Queue<UUID> expiredCheckQueue = new LinkedList<>();
+ private final LinkedList<QuestProgress> completionQueue = new LinkedList<>();
+ private final LinkedList<QuestProgressFile> fullCheckQueue = new LinkedList<>();
+ private final LinkedList<UUID> expiredCheckQueue = new LinkedList<>();
private final BukkitQuestsPlugin plugin;
private int expiredQuestsCheckCountdown;
@@ -147,4 +144,16 @@ public class BukkitQuestCompleter implements QuestCompleter, Runnable {
fullCheckQueue.add(questProgressFile);
}
+
+ public List<QuestProgress> getCompletionQueue() {
+ return Collections.unmodifiableList(completionQueue);
+ }
+
+ public List<QuestProgressFile> getFullCheckQueue() {
+ return Collections.unmodifiableList(fullCheckQueue);
+ }
+
+ public List<UUID> getExpiredCheckQueue() {
+ return Collections.unmodifiableList(expiredCheckQueue);
+ }
}
diff --git a/bukkit/src/main/java/com/leonardobishop/quests/bukkit/util/LogHistory.java b/bukkit/src/main/java/com/leonardobishop/quests/bukkit/util/LogHistory.java
new file mode 100644
index 00000000..293f7c1f
--- /dev/null
+++ b/bukkit/src/main/java/com/leonardobishop/quests/bukkit/util/LogHistory.java
@@ -0,0 +1,71 @@
+package com.leonardobishop.quests.bukkit.util;
+
+import com.leonardobishop.quests.common.logger.QuestsLogger;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.function.Supplier;
+
+public class LogHistory {
+
+ private final boolean enabled;
+
+ private final List<LogEntry> entries = new ArrayList<>();
+
+ public LogHistory(boolean enabled) {
+ this.enabled = enabled;
+ }
+
+ public void record(QuestsLogger.LoggingLevel type, Supplier<String> supplier) {
+ if (enabled) {
+ String entry = supplier.get();
+ String thread = Thread.currentThread().getName();
+ long time = System.currentTimeMillis();
+
+ LogEntry logEntry = new LogEntry(entry, type, thread, time);
+
+ synchronized (this) {
+ entries.add(logEntry);
+ }
+ }
+ }
+
+ public synchronized List<LogEntry> getEntries() {
+ return Collections.unmodifiableList(entries);
+ }
+
+ public boolean isEnabled() {
+ return enabled;
+ }
+
+ public static class LogEntry {
+ private final String entry;
+ private final QuestsLogger.LoggingLevel type;
+ private final String thread;
+ private final long time;
+
+ public LogEntry(String entry, QuestsLogger.LoggingLevel type, String thread, long time) {
+ this.entry = entry;
+ this.type = type;
+ this.thread = thread;
+ this.time = time;
+ }
+
+ public String getEntry() {
+ return entry;
+ }
+
+ public QuestsLogger.LoggingLevel getType() {
+ return type;
+ }
+
+ public String getThread() {
+ return thread;
+ }
+
+ public long getTime() {
+ return time;
+ }
+ }
+}
diff --git a/common/src/main/java/com/leonardobishop/quests/common/player/QPlayerManager.java b/common/src/main/java/com/leonardobishop/quests/common/player/QPlayerManager.java
index b9a814a0..1526fd9f 100644
--- a/common/src/main/java/com/leonardobishop/quests/common/player/QPlayerManager.java
+++ b/common/src/main/java/com/leonardobishop/quests/common/player/QPlayerManager.java
@@ -39,12 +39,12 @@ public class QPlayerManager {
Objects.requireNonNull(uuid, "uuid cannot be null");
QPlayer qPlayer = qPlayers.get(uuid);
- if (qPlayer == null) {
- plugin.getQuestsLogger().debug("QPlayer of " + uuid + " is null, but was requested:");
- if (plugin.getQuestsLogger().getServerLoggingLevel() == QuestsLogger.LoggingLevel.DEBUG) {
- Thread.dumpStack();
- }
- }
+// if (qPlayer == null) {
+// plugin.getQuestsLogger().debug("QPlayer of " + uuid + " is null, but was requested:");
+// if (plugin.getQuestsLogger().getServerLoggingLevel() == QuestsLogger.LoggingLevel.DEBUG) {
+// Thread.dumpStack();
+// }
+// }
return qPlayer;
}