From f8054a82a9b9aa108d97d14e775d20793b63563b Mon Sep 17 00:00:00 2001 From: KingRainbow44 Date: Fri, 12 May 2023 19:38:46 -0400 Subject: [PATCH] Add basic troubleshooting command --- .../command/commands/TroubleshootCommand.java | 46 ++++++++++++ .../java/emu/grasscutter/tools/Tools.java | 72 +++++++++++++++++-- 2 files changed, 114 insertions(+), 4 deletions(-) create mode 100644 src/main/java/emu/grasscutter/command/commands/TroubleshootCommand.java diff --git a/src/main/java/emu/grasscutter/command/commands/TroubleshootCommand.java b/src/main/java/emu/grasscutter/command/commands/TroubleshootCommand.java new file mode 100644 index 000000000..32db9838d --- /dev/null +++ b/src/main/java/emu/grasscutter/command/commands/TroubleshootCommand.java @@ -0,0 +1,46 @@ +package emu.grasscutter.command.commands; + +import emu.grasscutter.BuildConfig; +import emu.grasscutter.Grasscutter; +import emu.grasscutter.command.Command; +import emu.grasscutter.command.CommandHandler; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.tools.Tools; + +import java.util.List; + +@Command(label = "troubleshoot", aliases = {"helpme"}, + usage = "/troubleshoot", permission = "grasscutter.command.troubleshoot", + targetRequirement = Command.TargetRequirement.NONE) +public final class TroubleshootCommand implements CommandHandler { + @Override + public void execute(Player sender, Player targetPlayer, List args) { + // Collect server information. + var build = "%s (%s)".formatted( + BuildConfig.VERSION, BuildConfig.GIT_HASH); + var playerCount = Grasscutter.getGameServer() + .getPlayers().size(); + var resourceInfo = Tools.resourcesInfo(); + + // Collect configuration information. + var config = Grasscutter.getConfig(); + var gameOptions = config.server.game; + var questingEnabled = gameOptions.gameOptions.questing.enabled; + var scriptsEnabled = gameOptions.enableScriptInBigWorld; + + // TODO: Send to remote server (Grasscutter API) and send dump link. + CommandHandler.sendMessage(sender, """ + Troubleshooting/Debug Information + Revision: %s + Player Count: %d + Questing Enabled: %s + Scripts Enabled: %s + Operating System: %s + Resource Information: %s""" + .formatted( + build, playerCount, questingEnabled, scriptsEnabled, + System.getProperty("os.name"), resourceInfo.toString() + ) + ); + } +} diff --git a/src/main/java/emu/grasscutter/tools/Tools.java b/src/main/java/emu/grasscutter/tools/Tools.java index 8ac966dd1..ffe4f7bb9 100644 --- a/src/main/java/emu/grasscutter/tools/Tools.java +++ b/src/main/java/emu/grasscutter/tools/Tools.java @@ -1,8 +1,5 @@ package emu.grasscutter.tools; -import static emu.grasscutter.utils.FileUtils.getResourcePath; -import static emu.grasscutter.utils.Language.getTextMapKey; - import emu.grasscutter.GameConstants; import emu.grasscutter.Grasscutter; import emu.grasscutter.command.CommandHandler; @@ -14,10 +11,16 @@ import emu.grasscutter.data.excels.HomeWorldBgmData; import emu.grasscutter.data.excels.ItemData; import emu.grasscutter.data.excels.achievement.AchievementData; import emu.grasscutter.data.excels.avatar.AvatarData; +import emu.grasscutter.utils.FileUtils; +import emu.grasscutter.utils.JsonUtils; import emu.grasscutter.utils.Language; import emu.grasscutter.utils.Language.TextStrings; import it.unimi.dsi.fastutil.ints.Int2IntRBTreeMap; import it.unimi.dsi.fastutil.ints.Int2ObjectRBTreeMap; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.val; + import java.io.*; import java.nio.charset.StandardCharsets; import java.nio.file.Files; @@ -29,7 +32,9 @@ import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.IntStream; import java.util.stream.LongStream; -import lombok.val; + +import static emu.grasscutter.utils.FileUtils.getResourcePath; +import static emu.grasscutter.utils.Language.getTextMapKey; public final class Tools { /** @@ -398,4 +403,63 @@ public final class Tools { Grasscutter.getLogger().info("Invalid option. Will use EN (English) as fallback."); return "EN"; } + + /** + * Parses the 'resources.info' file found in resources. + * + * @return A {@link ResourceInfo} object containing the parsed data. + */ + public static ResourceInfo resourcesInfo() { + var file = FileUtils.getResourcePath("resources.info"); + try (var reader = Files.newBufferedReader(file, StandardCharsets.UTF_8)) { + var resourceInfo = ResourceInfo.builder(); + reader.lines().forEach(line -> { + var split = line.split(":"); + if (split.length != 2) return; + + var key = split[0].trim(); + var value = split[1].trim(); + + // Apply the value to the correct field. + switch (key) { + case "repo" -> resourceInfo.repository(value); + case "ver" -> resourceInfo.version(value); + case "patches" -> resourceInfo.patches(value); + case "scripts" -> resourceInfo.scripts( + ScriptsType.valueOf(value.toUpperCase())); + case "hasserverres" -> resourceInfo.hasServerResources( + Boolean.parseBoolean(value)); + case "hasscenescriptdata" -> resourceInfo.hasSceneScriptData( + Boolean.parseBoolean(value)); + } + }); + + return resourceInfo.build(); + } catch (Exception ignored) { + return new ResourceInfo( + null, null, null, + ScriptsType.UNKNOWN, false, false); + } + } + + @AllArgsConstructor @Builder + public static class ResourceInfo { + private final String repository; + private final String version; + private final String patches; + private final ScriptsType scripts; + private final boolean hasServerResources; + private final boolean hasSceneScriptData; + + @Override + public String toString() { + return JsonUtils.encode(this); + } + } + + public enum ScriptsType { + OFFICIAL, + DUMPED, + UNKNOWN + } }