Create/src/main/java/com/simibubi/create/infrastructure/debugInfo/DebugInformation.java
2023-10-22 11:03:28 +02:00

163 lines
5.7 KiB
Java

package com.simibubi.create.infrastructure.debugInfo;
import com.google.common.collect.ImmutableMap;
import com.jozufozu.flywheel.Flywheel;
import com.jozufozu.flywheel.backend.Backend;
import com.simibubi.create.Create;
import com.simibubi.create.foundation.mixin.accessor.SystemReportAccessor;
import com.simibubi.create.infrastructure.debugInfo.element.DebugInfoSection;
import net.minecraft.SharedConstants;
import net.minecraft.SystemReport;
import net.minecraft.Util;
import net.minecraft.client.Minecraft;
import com.simibubi.create.infrastructure.debugInfo.element.InfoElement;
import com.simibubi.create.infrastructure.debugInfo.element.InfoEntry;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.fml.ModList;
import net.minecraftforge.forgespi.language.IModInfo;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.annotation.Nullable;
import com.mojang.blaze3d.platform.GlUtil;
/**
* Allows for providing easily accessible debugging information.
* This info can be retrieved with the "/create debuginfo" command.
* This command copies all information to the clipboard, formatted for a GitHub issue.
* Addons are welcome to add their own sections. Registration must occur synchronously.
*/
public class DebugInformation {
private static final List<DebugInfoSection> client = new ArrayList<>();
private static final List<DebugInfoSection> server = new ArrayList<>();
private static final ImmutableMap<String, String> mcSystemInfo = Util.make(() -> {
SystemReport systemReport = new SystemReport();
SystemReportAccessor access = (SystemReportAccessor) systemReport;
return ImmutableMap.copyOf(access.getEntries());
});
public static void registerClientInfo(DebugInfoSection section) {
client.add(section);
}
public static void registerServerInfo(DebugInfoSection section) {
server.add(section);
}
public static void registerBothInfo(DebugInfoSection section) {
registerClientInfo(section);
registerServerInfo(section);
}
public static List<DebugInfoSection> getClientInfo() {
return client;
}
public static List<DebugInfoSection> getServerInfo() {
return server;
}
static {
DebugInfoSection.builder(Create.NAME)
.put("Mod Version", Create.VERSION)
.put("Forge Version", getVersionOfMod("forge"))
.put("Minecraft Version", SharedConstants.getCurrentVersion().getName())
.buildTo(DebugInformation::registerBothInfo);
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> {
DebugInfoSection.builder("Graphics")
.put("Flywheel Version", Flywheel.getVersion().toString())
.put("Flywheel Backend", () -> Backend.getBackendType().toString())
.put("OpenGL Renderer", GlUtil::getRenderer)
.put("OpenGL Version", GlUtil::getOpenGLVersion)
.put("Graphics Mode", () -> Minecraft.getInstance().options.graphicsMode.toString())
.buildTo(DebugInformation::registerClientInfo);
});
DebugInfoSection.builder("System Information")
.put("Operating System", SystemReportAccessor.getOPERATING_SYSTEM())
.put("Java Version", SystemReportAccessor.getJAVA_VERSION())
.put("JVM Flags", getMcSystemInfo("JVM Flags"))
.put("Memory", () -> getMcSystemInfo("Memory"))
.put("CPU", getCpuInfo())
.putAll(listAllGraphicsCards())
.buildTo(DebugInformation::registerBothInfo);
DebugInfoSection.builder("Other Mods")
.putAll(listAllOtherMods())
.buildTo(DebugInformation::registerBothInfo);
}
public static String getVersionOfMod(String id) {
return ModList.get().getModContainerById(id)
.map(mod -> mod.getModInfo().getVersion().toString())
.orElse("None");
}
public static Collection<InfoElement> listAllOtherMods() {
List<InfoElement> mods = new ArrayList<>();
ModList.get().forEachModContainer((id, mod) -> {
if (!id.equals(Create.ID) && !id.equals("forge") && !id.equals("minecraft") && !id.equals("flywheel")) {
IModInfo info = mod.getModInfo();
String name = info.getDisplayName();
String version = info.getVersion().toString();
mods.add(new InfoEntry(name, version));
}
});
return mods;
}
public static Collection<InfoElement> listAllGraphicsCards() {
List<InfoElement> cards = new ArrayList<>();
for (int i = 0; i < 10; i++) { // there won't be more than 10, right? right??
String name = getMcSystemInfo("Graphics card #" + i + " name");
String vendor = getMcSystemInfo("Graphics card #" + i + " vendor");
String vram = getMcSystemInfo("Graphics card #" + i + " VRAM (MB)");
if (name == null || vendor == null || vram == null)
break;
String key = "Graphics card #" + i;
String value = String.format("%s (%s); %s MB of VRAM", name, vendor, vram);
cards.add(new InfoEntry(key, value));
}
return cards.isEmpty() ? List.of(new InfoEntry("Graphics cards", "none")) : cards;
}
public static String getCpuInfo() {
String name = tryTrim(getMcSystemInfo("Processor Name"));
String freq = getMcSystemInfo("Frequency (GHz)");
String sockets = getMcSystemInfo("Number of physical packages");
String cores = getMcSystemInfo("Number of physical CPUs");
String threads = getMcSystemInfo("Number of logical CPUs");
return String.format("%s @ %s GHz; %s cores / %s threads on %s socket(s)", name, freq, cores, threads, sockets);
}
/**
* Get a system attribute provided by Minecraft.
* They can be found in the constructor of {@link SystemReport}.
*/
@Nullable
public static String getMcSystemInfo(String key) {
return mcSystemInfo.get(key);
}
public static String getIndent(int depth) {
return Stream.generate(() -> "\t").limit(depth).collect(Collectors.joining());
}
@Nullable
public static String tryTrim(@Nullable String s) {
return s == null ? null : s.trim();
}
}