diff options
5 files changed, 260 insertions, 76 deletions
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/ClientCommandBase.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/ClientCommandBase.java new file mode 100644 index 00000000..47174f32 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/ClientCommandBase.java @@ -0,0 +1,28 @@ +package io.github.moulberry.notenoughupdates.commands; + +import net.minecraft.command.CommandBase; +import net.minecraft.command.ICommandSender; + +public abstract class ClientCommandBase extends CommandBase { + + private final String name; + + protected ClientCommandBase(String name) { + this.name = name; + } + + @Override + public String getCommandName() { + return name; + } + + @Override + public String getCommandUsage(ICommandSender sender) { + return "/"+name; + } + + @Override + public boolean canCommandSenderUseCommand(ICommandSender sender) { + return true; + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/Commands.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/Commands.java index a63f3fde..9fbe27dd 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/commands/Commands.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/Commands.java @@ -91,7 +91,7 @@ public class Commands { ClientCommandHandler.instance.registerCommand(overlayPlacementsCommand); ClientCommandHandler.instance.registerCommand(enchantColourCommand); ClientCommandHandler.instance.registerCommand(neuAhCommand); - ClientCommandHandler.instance.registerCommand(pcStatsCommand); + ClientCommandHandler.instance.registerCommand(new StatsCommand()); ClientCommandHandler.instance.registerCommand(neumapCommand); ClientCommandHandler.instance.registerCommand(settingsCommand); ClientCommandHandler.instance.registerCommand(settingsCommand2); @@ -597,81 +597,6 @@ public class Commands { } }); - - SimpleCommand pcStatsCommand = new SimpleCommand("neustats", new SimpleCommand.ProcessCommandRunnable() { - public void processCommand(ICommandSender sender, String[] args) { - Minecraft mc = Minecraft.getMinecraft(); - StringBuilder builder = new StringBuilder(); - - if (args.length > 0 && args[0].toLowerCase().equals("modlist")){ - builder.append("```md\n"); - builder.append("# Mods Loaded").append("\n"); - for (ModContainer modContainer : Loader.instance().getActiveModList()) { - builder.append("[").append(modContainer.getName()).append("]") - .append("[").append(modContainer.getSource().getName()).append("]\n"); - } - builder.append("```"); - } else { - long memorySize = -1; - try { - memorySize = ((com.sun.management.OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean()).getTotalPhysicalMemorySize(); - } catch(Exception e){} - long maxMemory = Runtime.getRuntime().maxMemory(); - long totalMemory = Runtime.getRuntime().totalMemory(); - long freeMemory = Runtime.getRuntime().freeMemory(); - long currentMemory = totalMemory - freeMemory; - int modCount = Loader.instance().getModList().size(); - int activeModCount = Loader.instance().getActiveModList().size(); - - builder.append("```md\n"); - builder.append("# System Stats").append("\n"); - builder.append("[OS]").append("[").append(System.getProperty("os.name")).append("]").append("\n"); - builder.append("[CPU]").append("[").append(OpenGlHelper.getCpu()).append("]").append("\n"); - builder.append("[Display]").append("[").append(String.format("%dx%d (%s)", Display.getWidth(), Display.getHeight(), GL11.glGetString(GL11.GL_VENDOR))).append("]").append("\n"); - builder.append("[GPU]").append("[").append(GL11.glGetString(GL11.GL_RENDERER)).append("]").append("\n"); - builder.append("[GPU Driver]").append("[").append(GL11.glGetString(GL11.GL_VERSION)).append("]").append("\n"); - if(memorySize > 0) { - builder.append("[Maximum Memory]").append("[").append(memorySize / 1024L / 1024L).append("MB]").append("\n"); - } - builder.append("[Shaders]").append("[").append((""+OpenGlHelper.areShadersSupported()).toUpperCase()).append("]").append("\n"); - builder.append("[Framebuffers]").append("[").append((""+OpenGlHelper.isFramebufferEnabled()).toUpperCase()).append("]").append("\n"); - builder.append("# Java Stats").append("\n"); - builder.append("[Java]").append("[").append(String.format("%s %dbit", System.getProperty("java.version"), mc.isJava64bit() ? 64 : 32)).append("]").append("\n"); - builder.append("[Memory]").append("[").append(String.format("% 2d%% %03d/%03dMB", currentMemory * 100L / maxMemory, currentMemory / 1024L / 1024L, maxMemory / 1024L / 1024L)).append("]").append("\n"); - builder.append("[Memory Allocated]").append("[").append(String.format("% 2d%% %03dMB", totalMemory * 100L / maxMemory, totalMemory / 1024L / 1024L)).append("]").append("\n"); - builder.append("# Game Stats").append("\n"); - builder.append("[Current FPS]").append("[").append(Minecraft.getDebugFPS()).append("]").append("\n"); - builder.append("[Loaded Mods]").append("[").append(activeModCount).append("/").append(modCount).append("]").append("\n"); - builder.append("[Forge]").append("[").append(ForgeVersion.getVersion()).append("]").append("\n"); - builder.append("# Neu Settings").append("\n"); - builder.append("[API Key]").append("[").append(!NotEnoughUpdates.INSTANCE.config.apiKey.apiKey.isEmpty()).append("]").append("\n"); - builder.append("[On Skyblock]").append("[").append(NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()).append("]").append("\n"); - builder.append("[Mod Version]").append("[").append(Loader.instance().getIndexedModList().get(NotEnoughUpdates.INSTANCE.MODID).getSource().getName()).append("]").append("\n"); - builder.append("[SB Profile]").append("[").append(SBInfo.getInstance().currentProfile).append("]").append("\n"); - builder.append("# Repo Stats").append("\n"); - builder.append("[Last Commit]").append("[").append(NotEnoughUpdates.INSTANCE.manager.latestRepoCommit).append("]").append("\n"); - builder.append("[Loaded Items]").append("[").append(NotEnoughUpdates.INSTANCE.manager.getItemInformation().size()).append("]").append("\n"); - if (activeModCount <= 15) { - builder.append("# Mods Loaded").append("\n"); - for (ModContainer modContainer : Loader.instance().getActiveModList()) { - builder.append("[").append(modContainer.getName()).append("]") - .append("[").append(modContainer.getSource().getName()).append("]\n"); - } - builder.append("```"); - } else { - builder.append("```"); - } - } - try { - StringSelection clipboard = new StringSelection(builder.toString()); - Toolkit.getDefaultToolkit().getSystemClipboard().setContents(clipboard, clipboard); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.GOLD + "[" + EnumChatFormatting.RED + "NotEnoughUpdates" + EnumChatFormatting.GOLD + "]: " + EnumChatFormatting.GREEN + "Dev info copied to clipboard.")); - } catch (Exception ignored) { - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.GOLD + "[" + EnumChatFormatting.RED + "NotEnoughUpdates" + EnumChatFormatting.GOLD + "]: " + EnumChatFormatting.DARK_RED + "Could not copy to clipboard.")); - } - } - }); - public SimpleCommand.ProcessCommandRunnable viewProfileRunnable = new SimpleCommand.ProcessCommandRunnable() { public void processCommand(ICommandSender sender, String[] args) { if(!OpenGlHelper.isFramebufferEnabled()) { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/StatsCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/StatsCommand.java new file mode 100644 index 00000000..b61c58ed --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/StatsCommand.java @@ -0,0 +1,146 @@ +package io.github.moulberry.notenoughupdates.commands; + +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.util.DiscordMarkdownBuilder; +import io.github.moulberry.notenoughupdates.util.HastebinUploader; +import io.github.moulberry.notenoughupdates.util.SBInfo; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.OpenGlHelper; +import net.minecraft.command.ICommandSender; +import net.minecraft.util.BlockPos; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.EnumChatFormatting; +import net.minecraftforge.common.ForgeVersion; +import net.minecraftforge.fml.common.Loader; +import org.lwjgl.opengl.Display; +import org.lwjgl.opengl.GL11; + +import javax.management.JMX; +import javax.management.MBeanServer; +import javax.management.ObjectName; +import java.awt.*; +import java.awt.datatransfer.StringSelection; +import java.lang.management.ManagementFactory; +import java.util.List; +import java.util.Locale; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +public class StatsCommand extends ClientCommandBase { + + private final ExecutorService threadPool = Executors.newFixedThreadPool(1); + + public StatsCommand() { + super("neustats"); + } + + @Override + public void processCommand(ICommandSender sender, String[] args) { + if (args.length > 0){ + switch (args[0].toLowerCase(Locale.ROOT)) { + case "modlist": + clipboardAndSendMessage(createModList(new DiscordMarkdownBuilder()).toString()); + break; + case "dump": + modPrefixedMessage(EnumChatFormatting.GREEN + "This will upload a dump of the java classes your game has loaded how big they are and how many there are. This can take a few seconds as it is uploading to HasteBin."); + threadPool.submit(() -> { + try { + final MBeanServer server = ManagementFactory.getPlatformMBeanServer(); + final ObjectName objectName = ObjectName.getInstance("com.sun.management:type=DiagnosticCommand"); + final DiagnosticCommandMXBean proxy = JMX.newMXBeanProxy(server, objectName, DiagnosticCommandMXBean.class); + clipboardAndSendMessage(HastebinUploader.upload(proxy.gcClassHistogram(new String[0]).replace("[", "[]"), HastebinUploader.Mode.NORMAL)); + }catch (Exception e){ + clipboardAndSendMessage(null); + } + }); + break; + } + } else { + clipboardAndSendMessage(createStats()); + } + + } + + @Override + public List<String> addTabCompletionOptions(ICommandSender sender, String[] args, BlockPos pos) { + return args.length == 1 ? getListOfStringsMatchingLastWord(args, "modlist", "dump") : null; + } + + public interface DiagnosticCommandMXBean { + String gcClassHistogram(String[] array); + } + + private static void clipboardAndSendMessage(String data) { + if (data == null) { + modPrefixedMessage(EnumChatFormatting.DARK_RED + "Error occurred trying to perform command."); + return; + } + try { + StringSelection clipboard = new StringSelection(data); + Toolkit.getDefaultToolkit().getSystemClipboard().setContents(clipboard, clipboard); + modPrefixedMessage(EnumChatFormatting.GREEN + "Dev info copied to clipboard."); + } catch (Exception ignored) { + modPrefixedMessage(EnumChatFormatting.DARK_RED + "Could not copy to clipboard."); + } + } + + private static void modPrefixedMessage(String message) { + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.GOLD + "[" + EnumChatFormatting.RED + "NotEnoughUpdates" + EnumChatFormatting.GOLD + "]: " + message)); + + } + + private static String createStats() { + DiscordMarkdownBuilder builder = new DiscordMarkdownBuilder(); + long maxMemory = Runtime.getRuntime().maxMemory(); + long totalMemory = Runtime.getRuntime().totalMemory(); + long freeMemory = Runtime.getRuntime().freeMemory(); + long currentMemory = totalMemory - freeMemory; + int activeModCount = Loader.instance().getActiveModList().size(); + + builder.category("System Stats"); + builder.append("OS", System.getProperty("os.name")); + builder.append("CPU", OpenGlHelper.getCpu()); + builder.append("Display", String.format("%dx%d (%s)", Display.getWidth(), Display.getHeight(), GL11.glGetString(GL11.GL_VENDOR))); + builder.append("GPU", GL11.glGetString(GL11.GL_RENDERER)); + builder.append("GPU Driver", GL11.glGetString(GL11.GL_VERSION)); + if(getMemorySize() > 0) builder.append("Maximum Memory", (getMemorySize() / 1024L / 1024L) + "MB"); + builder.append("Shaders", (""+OpenGlHelper.isFramebufferEnabled()).toUpperCase()); + builder.category("Java Stats"); + builder.append("Java", String.format("%s %dbit", System.getProperty("java.version"), Minecraft.getMinecraft().isJava64bit() ? 64 : 32)); + builder.append("Memory", String.format("% 2d%% %03d/%03dMB", currentMemory * 100L / maxMemory, currentMemory / 1024L / 1024L, maxMemory / 1024L / 1024L)); + builder.append("Memory Allocated", String.format("% 2d%% %03dMB", totalMemory * 100L / maxMemory, totalMemory / 1024L / 1024L)); + builder.category("Game Stats"); + builder.append("FPS", String.valueOf(Minecraft.getDebugFPS())); + builder.append("Loaded Mods", String.valueOf(activeModCount)); + builder.append("Forge", ForgeVersion.getVersion()); + builder.category("Neu Settings"); + builder.append("API Key", NotEnoughUpdates.INSTANCE.config.apiKey.apiKey.isEmpty() ? "FALSE" : "TRUE"); + builder.append("On Skyblock", NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard() ? "TRUE" : "FALSE"); + builder.append("Mod Version", Loader.instance().getIndexedModList().get(NotEnoughUpdates.MODID).getSource().getName()); + builder.append("SB Profile", SBInfo.getInstance().currentProfile); + builder.category("Repo Stats"); + builder.append("Last Commit", NotEnoughUpdates.INSTANCE.manager.latestRepoCommit); + builder.append("Loaded Items", String.valueOf(NotEnoughUpdates.INSTANCE.manager.getItemInformation().size())); + if (activeModCount <= 15) createModList(builder); + + return builder.toString(); + } + + private static DiscordMarkdownBuilder createModList(DiscordMarkdownBuilder builder) { + builder.category("Mods Loaded"); + Loader.instance().getActiveModList().forEach(mod -> builder.append(mod.getName(), mod.getSource().getName())); + return builder; + } + + private static long getMemorySize(){ + try { + return ((com.sun.management.OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean()).getTotalPhysicalMemorySize(); + } catch(Exception e){ + try { + return ((com.sun.management.UnixOperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean()).getTotalPhysicalMemorySize(); + } catch(Exception ignored){/*IGNORE*/} + } + return -1; + } + +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/DiscordMarkdownBuilder.java b/src/main/java/io/github/moulberry/notenoughupdates/util/DiscordMarkdownBuilder.java new file mode 100644 index 00000000..ccffa313 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/util/DiscordMarkdownBuilder.java @@ -0,0 +1,26 @@ +package io.github.moulberry.notenoughupdates.util; + +public class DiscordMarkdownBuilder { + + private final StringBuilder builder; + + public DiscordMarkdownBuilder() { + this.builder = new StringBuilder(); + this.builder.append("```md\n"); + } + + public DiscordMarkdownBuilder category(String name) { + builder.append("# ").append(name).append("\n"); + return this; + } + + public DiscordMarkdownBuilder append(String key, Object value) { + builder.append("[").append(key).append("]").append("[").append(value).append("]").append("\n"); + return this; + } + + @Override + public String toString() { + return builder.append("```").toString(); + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/HastebinUploader.java b/src/main/java/io/github/moulberry/notenoughupdates/util/HastebinUploader.java new file mode 100644 index 00000000..70753e10 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/util/HastebinUploader.java @@ -0,0 +1,59 @@ +package io.github.moulberry.notenoughupdates.util; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import org.apache.commons.io.Charsets; +import org.apache.commons.io.IOUtils; + +import java.net.HttpURLConnection; +import java.net.URL; +import java.nio.charset.StandardCharsets; + +/** + * @author ThatGravyBoat + */ +public class HastebinUploader { + + private static final String UPLOAD_URL = "https://hst.sh/documents"; + private static final String RETURN_URL = "https://hst.sh/"; + private static final String RAW_RETURN_URL = "https://hst.sh/raw/"; + + private static final Gson GSON = new Gson(); + + /** + * @param data the data you want to upload + * @param mode the mode in which the thing should return NORMAL = returns the url, RAW = returns the raw url, NO_URL = returns the slug. + * @return The url if mode is NORMAL OR RAW, the slug if mode is NO_URL, and null if an error occurred. + */ + public static String upload(String data, Mode mode){ + try { + byte[] bytes = data.getBytes(StandardCharsets.UTF_8); + HttpURLConnection connection = (HttpURLConnection)new URL(UPLOAD_URL).openConnection(); + connection.setRequestMethod("POST"); + connection.addRequestProperty("User-Agent", "Minecraft Mod ("+ NotEnoughUpdates.MODID +"/"+NotEnoughUpdates.VERSION+")"); + connection.addRequestProperty("Content-Length", String.valueOf(bytes.length)); + connection.setReadTimeout(15000); + connection.setConnectTimeout(15000); + connection.setDoOutput(true); + connection.getOutputStream().write(bytes); + final JsonObject json = GSON.fromJson(IOUtils.toString(connection.getInputStream(), Charsets.UTF_8), JsonObject.class); + if (!json.has("key")) return null; + final String key = json.get("key").getAsString(); + switch (mode) { + case RAW: return RAW_RETURN_URL + key; + case NORMAL: return RETURN_URL + key; + case NO_URL: return key; + } + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + public enum Mode { + NORMAL, + RAW, + NO_URL + } +} |