Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion core/src/main/java/com/rexcantor64/triton/Triton.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.rexcantor64.triton;

import com.google.gson.JsonElement;
import com.rexcantor64.triton.api.language.LanguageParser;
import com.rexcantor64.triton.api.legacy.LegacyLanguageParser;
import com.rexcantor64.triton.bridge.BridgeManager;
Expand All @@ -19,8 +20,8 @@
import com.rexcantor64.triton.logger.TritonLogger;
import com.rexcantor64.triton.migration.LanguageMigration;
import com.rexcantor64.triton.packetinterceptor.PacketEventsManager;
import com.rexcantor64.triton.player.TritonLanguagePlayer;
import com.rexcantor64.triton.player.PlayerManager;
import com.rexcantor64.triton.player.TritonLanguagePlayer;
import com.rexcantor64.triton.plugin.Platform;
import com.rexcantor64.triton.plugin.PluginLoader;
import com.rexcantor64.triton.storage.LocalStorage;
Expand All @@ -31,6 +32,7 @@
import com.rexcantor64.triton.web.TwinManager;
import lombok.Getter;
import lombok.val;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.io.File;
Expand Down Expand Up @@ -193,6 +195,8 @@ public Configuration loadYAML(String fileName, String internalFileName) {

public abstract String getVersion();

public abstract @NotNull JsonElement getPlatformDebugInfo();

protected abstract void startConfigRefreshTask();

public abstract void runAsync(Runnable runnable);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import com.rexcantor64.triton.commands.handler.exceptions.NoPermissionException;
import com.rexcantor64.triton.commands.handler.exceptions.UnsupportedPlatformException;
import com.rexcantor64.triton.debug.LoadDump;
import com.rexcantor64.triton.utils.DebugUtils;
import lombok.val;

import java.io.IOException;
Expand Down Expand Up @@ -65,6 +66,9 @@ public void handleCommand(CommandEvent event) throws NoPermissionException, Unsu
}

switch (subcommand.get()) {
case INFO:
handleInfoCommand(event);
break;
case DUMP:
handleDumpCommand(event);
break;
Expand All @@ -74,6 +78,15 @@ public void handleCommand(CommandEvent event) throws NoPermissionException, Unsu
}
}

public void handleInfoCommand(CommandEvent event) {
val debugInfo = DebugUtils.generateDebugInfo();
val path = DebugUtils.saveDebugInfo(debugInfo);
if (path == null) {
sendMessage(event, "debug.info.error");
} else {
sendMessage(event, "debug.info.success", path);
}
}

public void handleDumpCommand(CommandEvent event) {
val sender = event.getSender();
Expand Down Expand Up @@ -302,6 +315,7 @@ private enum TargetPlatform {
}

private enum Subcommand {
INFO,
DUMP,
LOAD
}
Expand Down
11 changes: 11 additions & 0 deletions core/src/main/java/com/rexcantor64/triton/config/MainConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import com.rexcantor64.triton.api.config.TritonConfig;
import com.rexcantor64.triton.config.interfaces.Configuration;
import com.rexcantor64.triton.language.Language;
import com.rexcantor64.triton.utils.DebugUtils.GsonExclude;
import com.rexcantor64.triton.utils.YAMLUtils;
import lombok.Cleanup;
import lombok.Getter;
Expand Down Expand Up @@ -42,6 +43,7 @@ public class MainConfig implements TritonConfig {
}.getType();

@ToString.Exclude
@GsonExclude
private transient final Triton<?, ?> main;
@Setter
private List<Language> languages;
Expand All @@ -54,6 +56,7 @@ public class MainConfig implements TritonConfig {
private boolean bungeecord;
private int configAutoRefresh;
@ToString.Exclude
@GsonExclude
private String twinToken;
private List<String> commandAliases;
private String parser = "adventure";
Expand Down Expand Up @@ -103,16 +106,22 @@ public class MainConfig implements TritonConfig {
private String storageType = "local";
private String serverName;
@ToString.Exclude
@GsonExclude
private String databaseHost;
@ToString.Exclude
@GsonExclude
private int databasePort;
@ToString.Exclude
@GsonExclude
private String databaseName;
@ToString.Exclude
@GsonExclude
private String databaseUser;
@ToString.Exclude
@GsonExclude
private String databasePassword;
@ToString.Exclude
@GsonExclude
private String databaseTablePrefix;
private int databaseMysqlPoolMaxSize;
private int databaseMysqlPoolMinIdle;
Expand Down Expand Up @@ -333,6 +342,8 @@ public static class FeatureSyntax implements com.rexcantor64.triton.api.config.F
private final String lang;
private final String args;
private final String arg;
@ToString.Exclude
@GsonExclude
private boolean interactive = false;

private static FeatureSyntax fromSection(Configuration section) {
Expand Down
94 changes: 94 additions & 0 deletions core/src/main/java/com/rexcantor64/triton/utils/DebugUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package com.rexcantor64.triton.utils;

import com.google.gson.ExclusionStrategy;
import com.google.gson.FieldAttributes;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import com.rexcantor64.triton.Triton;
import lombok.Cleanup;
import lombok.val;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.nio.file.Path;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class DebugUtils {

public static String generateDebugInfo() {
Gson gson = new GsonBuilder().setExclusionStrategies(new ExclusionStrategy() {
@Override
public boolean shouldSkipField(FieldAttributes fieldAttributes) {
return fieldAttributes.getAnnotation(GsonExclude.class) != null;
}

@Override
public boolean shouldSkipClass(Class<?> clazz) {
return clazz.getAnnotation(GsonExclude.class) != null;
}
}).setPrettyPrinting().create();
val instance = Triton.get();

JsonObject root = new JsonObject();
root.addProperty("tritonVersion", instance.getVersion());
root.addProperty("platform", Triton.platform().toString());
root.add("loaderFlags", gson.toJsonTree(instance.getLoader().getLoaderFlags()));
root.add("platformData", instance.getPlatformDebugInfo());
root.addProperty("textTranslationCount", instance.getTranslationManager().getTextTranslationCount());
root.addProperty("signTranslationCount", instance.getTranslationManager().getSignTranslationCount());
root.add("config", gson.toJsonTree(instance.getConfig()));

return gson.toJson(root);
}

/**
*
* @return The path of the saved file, relative to the plugin data dir
*/
public static @Nullable String saveDebugInfo(@NotNull String contents) {
String date = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH_mm_ss"));

String fileName = String.format("triton-%s-%s.json", Triton.platform().toString().toLowerCase(Locale.ROOT), date);

Path tritonFolderPath = Triton.get().getDataFolder().toPath();
Path infoFolderPath = tritonFolderPath.resolve("debug-info");
Path infoPath = infoFolderPath.resolve(fileName);

File infoFolderFile = infoFolderPath.toFile();
if (!infoFolderFile.isDirectory() && !infoFolderFile.mkdirs()) {
Triton.get().getLogger().logError("Failed to create \"%1\" folder!", infoFolderPath.toAbsolutePath().toString());
return null;
}

File infoFile = infoPath.toFile();

try {
@Cleanup
val writer = new BufferedWriter(new FileWriter(infoFile, true));

writer.write(contents);
writer.write("\n");

return tritonFolderPath.relativize(infoPath).toString();
} catch (IOException exception) {
Triton.get().getLogger().logError(exception, "Failed writing to debug info %1!", infoPath.toString());
return null;
}
}

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface GsonExclude {
}
}
3 changes: 3 additions & 0 deletions core/src/main/resources/messages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,9 @@ debug:
invalid: "&cProvided line number '&4%1&c' is not a valid number"
success:
sent: '&aSend &6%1&a message(s)!'
info:
error: "&cThere was an error dumping info about the plugin. See console for details."
success: "&aDumped plugin info to <plugin dir>/%1"

info-command:
- "&8-------[ &b&lTriton&8 ]-------"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.rexcantor64.triton.bungeecord;

import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.rexcantor64.triton.Triton;
import com.rexcantor64.triton.bungeecord.bridge.BungeeBridgeManager;
import com.rexcantor64.triton.bungeecord.commands.handler.BungeeCommand;
Expand All @@ -21,13 +23,16 @@
import net.md_5.bungee.api.connection.Connection;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.plugin.Plugin;
import net.md_5.bungee.api.plugin.PluginDescription;
import net.md_5.bungee.api.scheduler.ScheduledTask;
import net.md_5.bungee.netty.PipelineUtils;
import org.bstats.bungeecord.Metrics;
import org.bstats.charts.SingleLineChart;
import org.jetbrains.annotations.NotNull;

import java.io.File;
import java.lang.reflect.Method;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

Expand Down Expand Up @@ -171,4 +176,20 @@ public UUID getPlayerUUIDFromString(String input) {
protected String getConfigFileName() {
return "config_bungeecord";
}

private Optional<String> getPacketEventsVersion() {
return Optional.ofNullable(getLoader().getPlugin().getProxy().getPluginManager().getPlugin("packetevents"))
.map(Plugin::getDescription)
.map(PluginDescription::getVersion);
}

@Override
public @NotNull JsonElement getPlatformDebugInfo() {
val obj = new JsonObject();
val proxy = getLoader().getPlugin().getProxy();
obj.addProperty("serverName", proxy.getName());
obj.addProperty("serverVersion", proxy.getVersion());
getPacketEventsVersion().ifPresent(version -> obj.addProperty("packetEventsVersion", version));
return obj;
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.rexcantor64.triton.spigot;

import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.rexcantor64.triton.Triton;
import com.rexcantor64.triton.api.players.LanguagePlayer;
import com.rexcantor64.triton.player.PlayerManager;
Expand Down Expand Up @@ -30,7 +32,9 @@
import org.bukkit.command.CommandMap;
import org.bukkit.command.PluginCommand;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginDescriptionFile;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.io.File;
Expand Down Expand Up @@ -281,4 +285,28 @@ public boolean isPaperProxyMode() {
return false;
}
}

private Optional<String> getProtocolLibVersion() {
return getPluginVersion("ProtocolLib");
}

private Optional<String> getPacketEventsVersion() {
return getPluginVersion("packetevents");
}

private Optional<String> getPluginVersion(String name) {
return Optional.ofNullable(Bukkit.getPluginManager().getPlugin(name))
.map(Plugin::getDescription)
.map(PluginDescriptionFile::getVersion);
}

@Override
public @NotNull JsonElement getPlatformDebugInfo() {
val obj = new JsonObject();
obj.addProperty("serverName", Bukkit.getName());
obj.addProperty("serverVersion", Bukkit.getVersion());
getProtocolLibVersion().ifPresent(version -> obj.addProperty("protocolLibVersion", version));
getPacketEventsVersion().ifPresent(version -> obj.addProperty("packetEventsVersion", version));
return obj;
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.rexcantor64.triton.velocity;

import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.rexcantor64.triton.Triton;
import com.rexcantor64.triton.player.PlayerManager;
import com.rexcantor64.triton.plugin.PluginLoader;
Expand All @@ -10,6 +12,8 @@
import com.rexcantor64.triton.velocity.packetinterceptor.VelocityPacketEventsManager;
import com.rexcantor64.triton.velocity.player.VelocityLanguagePlayer;
import com.rexcantor64.triton.velocity.plugin.VelocityPlugin;
import com.velocitypowered.api.plugin.PluginContainer;
import com.velocitypowered.api.plugin.PluginDescription;
import com.velocitypowered.api.proxy.ProxyServer;
import com.velocitypowered.api.proxy.messages.ChannelIdentifier;
import com.velocitypowered.api.proxy.messages.MinecraftChannelIdentifier;
Expand All @@ -19,8 +23,10 @@
import lombok.val;
import org.bstats.charts.SingleLineChart;
import org.bstats.velocity.Metrics;
import org.jetbrains.annotations.NotNull;

import java.io.File;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

Expand Down Expand Up @@ -129,4 +135,21 @@ public UUID getPlayerUUIDFromString(String input) {
protected String getConfigFileName() {
return "config_velocity";
}

private Optional<String> getPacketEventsVersion() {
return getLoader().getServer().getPluginManager().getPlugin("packetevents")
.map(PluginContainer::getDescription)
.flatMap(PluginDescription::getVersion);
}

@Override
public @NotNull JsonElement getPlatformDebugInfo() {
val obj = new JsonObject();
val version = getLoader().getServer().getVersion();
obj.addProperty("serverName", version.getName());
obj.addProperty("serverVersion", version.getVersion());
obj.addProperty("serverVendor", version.getVendor());
getPacketEventsVersion().ifPresent(v -> obj.addProperty("packetEventsVersion", v));
return obj;
}
}