More crash report tweaks. Put a button to open the generated crash report on the error screen, tweak formatting of crash report, and add the enhanced stack trace data (transformers et al)
Signed-off-by: cpw <cpw+github@weeksfamily.ca>
This commit is contained in:
parent
15733a18e4
commit
43391c009c
5 changed files with 60 additions and 12 deletions
|
@ -8,7 +8,24 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
public String func_71501_a() {
|
public String func_71501_a() {
|
||||||
@@ -121,23 +122,13 @@
|
@@ -87,14 +88,8 @@
|
||||||
|
if (this.field_85060_g != null && this.field_85060_g.length > 0) {
|
||||||
|
p_71506_1_.append("-- Head --\n");
|
||||||
|
p_71506_1_.append("Thread: ").append(Thread.currentThread().getName()).append("\n");
|
||||||
|
- p_71506_1_.append("Stacktrace:\n");
|
||||||
|
-
|
||||||
|
- for(StackTraceElement stacktraceelement : this.field_85060_g) {
|
||||||
|
- p_71506_1_.append("\t").append("at ").append((Object)stacktraceelement);
|
||||||
|
- p_71506_1_.append("\n");
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- p_71506_1_.append("\n");
|
||||||
|
+ p_71506_1_.append("Stacktrace:");
|
||||||
|
+ p_71506_1_.append(net.minecraftforge.fml.CrashReportExtender.generateEnhancedStackTrace(this.field_85060_g));
|
||||||
|
}
|
||||||
|
|
||||||
|
for(CrashReportCategory crashreportcategory : this.field_71512_c) {
|
||||||
|
@@ -121,23 +116,13 @@
|
||||||
throwable.setStackTrace(this.field_71511_b.getStackTrace());
|
throwable.setStackTrace(this.field_71511_b.getStackTrace());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,20 @@
|
||||||
return this.field_85075_d.length;
|
return this.field_85075_d.length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -158,6 +160,10 @@
|
@@ -145,11 +147,7 @@
|
||||||
|
|
||||||
|
if (this.field_85075_d != null && this.field_85075_d.length > 0) {
|
||||||
|
p_85072_1_.append("\nStacktrace:");
|
||||||
|
-
|
||||||
|
- for(StackTraceElement stacktraceelement : this.field_85075_d) {
|
||||||
|
- p_85072_1_.append("\n\tat ");
|
||||||
|
- p_85072_1_.append((Object)stacktraceelement);
|
||||||
|
- }
|
||||||
|
+ p_85072_1_.append(net.minecraftforge.fml.CrashReportExtender.generateEnhancedStackTrace(this.field_85075_d));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
@@ -158,6 +156,10 @@
|
||||||
return this.field_85075_d;
|
return this.field_85075_d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
package net.minecraftforge.fml;
|
package net.minecraftforge.fml;
|
||||||
|
|
||||||
import cpw.mods.modlauncher.log.TransformingThrowablePatternConverter;
|
import cpw.mods.modlauncher.log.TransformingThrowablePatternConverter;
|
||||||
|
import joptsimple.internal.Strings;
|
||||||
import net.minecraft.crash.CrashReport;
|
import net.minecraft.crash.CrashReport;
|
||||||
import net.minecraft.crash.CrashReportCategory;
|
import net.minecraft.crash.CrashReportCategory;
|
||||||
import net.minecraftforge.fml.common.ICrashCallable;
|
import net.minecraftforge.fml.common.ICrashCallable;
|
||||||
|
@ -67,13 +68,23 @@ public class CrashReportExtender
|
||||||
public static void addCrashReportHeader(StringBuilder stringbuilder, CrashReport crashReport)
|
public static void addCrashReportHeader(StringBuilder stringbuilder, CrashReport crashReport)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String generateEnhancedStackTrace(final Throwable throwable) {
|
public static String generateEnhancedStackTrace(final Throwable throwable) {
|
||||||
return TransformingThrowablePatternConverter.generateEnhancedStackTrace(throwable);
|
return generateEnhancedStackTrace(throwable, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String generateEnhancedStackTrace(final StackTraceElement[] stacktrace) {
|
||||||
|
final Throwable t = new Throwable();
|
||||||
|
t.setStackTrace(stacktrace);
|
||||||
|
return generateEnhancedStackTrace(t, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String generateEnhancedStackTrace(final Throwable throwable, boolean header) {
|
||||||
|
final String s = TransformingThrowablePatternConverter.generateEnhancedStackTrace(throwable);
|
||||||
|
return header ? s : s.substring(s.indexOf(Strings.LINE_SEPARATOR));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static void dumpModLoadingCrashReport(final Logger logger, final LoadingFailedException error, final File topLevelDir) {
|
public static File dumpModLoadingCrashReport(final Logger logger, final LoadingFailedException error, final File topLevelDir) {
|
||||||
final CrashReport crashReport = CrashReport.makeCrashReport(new Exception("Mod Loading has failed"), "Mod loading error has occurred");
|
final CrashReport crashReport = CrashReport.makeCrashReport(new Exception("Mod Loading has failed"), "Mod loading error has occurred");
|
||||||
error.getErrors().forEach(mle -> {
|
error.getErrors().forEach(mle -> {
|
||||||
final Optional<IModInfo> modInfo = Optional.ofNullable(mle.getModInfo());
|
final Optional<IModInfo> modInfo = Optional.ofNullable(mle.getModInfo());
|
||||||
|
@ -81,16 +92,16 @@ public class CrashReportExtender
|
||||||
Throwable cause = mle.getCause();
|
Throwable cause = mle.getCause();
|
||||||
int depth = 0;
|
int depth = 0;
|
||||||
while (cause != null && cause.getCause() != null && cause.getCause()!=cause) {
|
while (cause != null && cause.getCause() != null && cause.getCause()!=cause) {
|
||||||
category.addDetail("Caused by "+(depth++), cause +"\n\t\t"+ Arrays.stream(cause.getStackTrace()).map(Objects::toString).collect(Collectors.joining("\n\t\t")));
|
category.addDetail("Caused by "+(depth++), cause + generateEnhancedStackTrace(cause.getStackTrace()).replaceAll(Strings.LINE_SEPARATOR+"\t", "\n\t\t"));
|
||||||
cause = cause.getCause();
|
cause = cause.getCause();
|
||||||
}
|
}
|
||||||
if (cause != null)
|
if (cause != null)
|
||||||
category.applyStackTrace(cause);
|
category.applyStackTrace(cause);
|
||||||
category.addDetail("Mod File", () -> modInfo.map(IModInfo::getOwningFile).map(t->((ModFileInfo)t).getFile().getFileName()).orElse("NO FILE INFO"));
|
category.addDetail("Mod File", () -> modInfo.map(IModInfo::getOwningFile).map(t->((ModFileInfo)t).getFile().getFileName()).orElse("NO FILE INFO"));
|
||||||
category.addDetail("Failure message", () -> mle.getCleanMessage().replace("\n", "\n\t\t"));
|
category.addDetail("Failure message", () -> mle.getCleanMessage().replace("\n", "\n\t\t"));
|
||||||
category.addDetail("Exception message", Objects.toString(cause, "MISSING EXCEPTION MESSAGE"));
|
|
||||||
category.addDetail("Mod Version", () -> modInfo.map(IModInfo::getVersion).map(Object::toString).orElse("NO MOD INFO AVAILABLE"));
|
category.addDetail("Mod Version", () -> modInfo.map(IModInfo::getVersion).map(Object::toString).orElse("NO MOD INFO AVAILABLE"));
|
||||||
category.addDetail("Mod Issue URL", () -> modInfo.map(IModInfo::getOwningFile).map(ModFileInfo.class::cast).flatMap(mfi->mfi.getConfigElement("issueTrackerURL")).orElse("NOT PROVIDED").toString());
|
category.addDetail("Mod Issue URL", () -> modInfo.map(IModInfo::getOwningFile).map(ModFileInfo.class::cast).flatMap(mfi->mfi.<String>getConfigElement("issueTrackerURL")).orElse("NOT PROVIDED"));
|
||||||
|
category.addDetail("Exception message", Objects.toString(cause, "MISSING EXCEPTION MESSAGE"));
|
||||||
});
|
});
|
||||||
final File file1 = new File(topLevelDir, "crash-reports");
|
final File file1 = new File(topLevelDir, "crash-reports");
|
||||||
final File file2 = new File(file1, "crash-" + (new SimpleDateFormat("yyyy-MM-dd_HH.mm.ss")).format(new Date()) + "-fml.txt");
|
final File file2 = new File(file1, "crash-" + (new SimpleDateFormat("yyyy-MM-dd_HH.mm.ss")).format(new Date()) + "-fml.txt");
|
||||||
|
@ -100,5 +111,6 @@ public class CrashReportExtender
|
||||||
logger.fatal("Failed to save crash report");
|
logger.fatal("Failed to save crash report");
|
||||||
}
|
}
|
||||||
System.out.print(crashReport.getCompleteReport());
|
System.out.print(crashReport.getCompleteReport());
|
||||||
|
return file2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -182,16 +182,17 @@ public class ClientModLoader
|
||||||
}
|
}
|
||||||
warnings = Collections.emptyList(); //Clear warnings, as the user does not want to see them
|
warnings = Collections.emptyList(); //Clear warnings, as the user does not want to see them
|
||||||
}
|
}
|
||||||
|
File dumpedLocation = null;
|
||||||
if (error == null) {
|
if (error == null) {
|
||||||
// We can finally start the forge eventbus up
|
// We can finally start the forge eventbus up
|
||||||
MinecraftForge.EVENT_BUS.start();
|
MinecraftForge.EVENT_BUS.start();
|
||||||
} else {
|
} else {
|
||||||
// Double check we have the langs loaded for forge
|
// Double check we have the langs loaded for forge
|
||||||
LanguageHook.loadForgeAndMCLangs();
|
LanguageHook.loadForgeAndMCLangs();
|
||||||
CrashReportExtender.dumpModLoadingCrashReport(LOGGER, error, mc.gameDir);
|
dumpedLocation = CrashReportExtender.dumpModLoadingCrashReport(LOGGER, error, mc.gameDir);
|
||||||
}
|
}
|
||||||
if (error != null || !warnings.isEmpty()) {
|
if (error != null || !warnings.isEmpty()) {
|
||||||
mc.displayGuiScreen(new LoadingErrorScreen(error, warnings));
|
mc.displayGuiScreen(new LoadingErrorScreen(error, warnings, dumpedLocation));
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
ClientHooks.logMissingTextureErrors();
|
ClientHooks.logMissingTextureErrors();
|
||||||
|
|
|
@ -41,6 +41,7 @@ import net.minecraftforge.fml.loading.FMLPaths;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -53,17 +54,19 @@ public class LoadingErrorScreen extends ErrorScreen {
|
||||||
private final Path logFile;
|
private final Path logFile;
|
||||||
private final List<ModLoadingException> modLoadErrors;
|
private final List<ModLoadingException> modLoadErrors;
|
||||||
private final List<ModLoadingWarning> modLoadWarnings;
|
private final List<ModLoadingWarning> modLoadWarnings;
|
||||||
|
private final Path dumpedLocation;
|
||||||
private LoadingEntryList entryList;
|
private LoadingEntryList entryList;
|
||||||
private ITextComponent errorHeader;
|
private ITextComponent errorHeader;
|
||||||
private ITextComponent warningHeader;
|
private ITextComponent warningHeader;
|
||||||
|
|
||||||
public LoadingErrorScreen(LoadingFailedException loadingException, List<ModLoadingWarning> warnings)
|
public LoadingErrorScreen(LoadingFailedException loadingException, List<ModLoadingWarning> warnings, final File dumpedLocation)
|
||||||
{
|
{
|
||||||
super(new StringTextComponent("Loading Error"), null);
|
super(new StringTextComponent("Loading Error"), null);
|
||||||
this.modLoadWarnings = warnings;
|
this.modLoadWarnings = warnings;
|
||||||
this.modLoadErrors = loadingException == null ? Collections.emptyList() : loadingException.getErrors();
|
this.modLoadErrors = loadingException == null ? Collections.emptyList() : loadingException.getErrors();
|
||||||
this.modsDir = FMLPaths.MODSDIR.get();
|
this.modsDir = FMLPaths.MODSDIR.get();
|
||||||
this.logFile = FMLPaths.GAMEDIR.get().resolve(Paths.get("logs","latest.log"));
|
this.logFile = FMLPaths.GAMEDIR.get().resolve(Paths.get("logs","latest.log"));
|
||||||
|
this.dumpedLocation = dumpedLocation.toPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -76,7 +79,7 @@ public class LoadingErrorScreen extends ErrorScreen {
|
||||||
this.errorHeader = new StringTextComponent(TextFormatting.RED + ForgeI18n.parseMessage("fml.loadingerrorscreen.errorheader", this.modLoadErrors.size()) + TextFormatting.RESET);
|
this.errorHeader = new StringTextComponent(TextFormatting.RED + ForgeI18n.parseMessage("fml.loadingerrorscreen.errorheader", this.modLoadErrors.size()) + TextFormatting.RESET);
|
||||||
this.warningHeader = new StringTextComponent(TextFormatting.YELLOW + ForgeI18n.parseMessage("fml.loadingerrorscreen.warningheader", this.modLoadErrors.size()) + TextFormatting.RESET);
|
this.warningHeader = new StringTextComponent(TextFormatting.YELLOW + ForgeI18n.parseMessage("fml.loadingerrorscreen.warningheader", this.modLoadErrors.size()) + TextFormatting.RESET);
|
||||||
|
|
||||||
int yOffset = this.modLoadErrors.isEmpty() ? 46 : 38;
|
int yOffset = 46;
|
||||||
this.func_230480_a_(new ExtendedButton(50, this.field_230709_l_ - yOffset, this.field_230708_k_ / 2 - 55, 20, new StringTextComponent(ForgeI18n.parseMessage("fml.button.open.mods.folder")), b -> Util.getOSType().openFile(modsDir.toFile())));
|
this.func_230480_a_(new ExtendedButton(50, this.field_230709_l_ - yOffset, this.field_230708_k_ / 2 - 55, 20, new StringTextComponent(ForgeI18n.parseMessage("fml.button.open.mods.folder")), b -> Util.getOSType().openFile(modsDir.toFile())));
|
||||||
this.func_230480_a_(new ExtendedButton(this.field_230708_k_ / 2 + 5, this.field_230709_l_ - yOffset, this.field_230708_k_ / 2 - 55, 20, new StringTextComponent(ForgeI18n.parseMessage("fml.button.open.file", logFile.getFileName())), b -> Util.getOSType().openFile(logFile.toFile())));
|
this.func_230480_a_(new ExtendedButton(this.field_230708_k_ / 2 + 5, this.field_230709_l_ - yOffset, this.field_230708_k_ / 2 - 55, 20, new StringTextComponent(ForgeI18n.parseMessage("fml.button.open.file", logFile.getFileName())), b -> Util.getOSType().openFile(logFile.toFile())));
|
||||||
if (this.modLoadErrors.isEmpty()) {
|
if (this.modLoadErrors.isEmpty()) {
|
||||||
|
@ -84,6 +87,8 @@ public class LoadingErrorScreen extends ErrorScreen {
|
||||||
ClientHooks.logMissingTextureErrors();
|
ClientHooks.logMissingTextureErrors();
|
||||||
this.field_230706_i_.displayGuiScreen(null);
|
this.field_230706_i_.displayGuiScreen(null);
|
||||||
}));
|
}));
|
||||||
|
} else {
|
||||||
|
this.func_230480_a_(new ExtendedButton(this.field_230708_k_ / 4, this.field_230709_l_ - 24, this.field_230708_k_ / 2, 20, new StringTextComponent(ForgeI18n.parseMessage("fml.button.open.file", dumpedLocation.getFileName())), b -> Util.getOSType().openFile(dumpedLocation.toFile())));
|
||||||
}
|
}
|
||||||
|
|
||||||
this.entryList = new LoadingEntryList(this, this.modLoadErrors, this.modLoadWarnings);
|
this.entryList = new LoadingEntryList(this, this.modLoadErrors, this.modLoadWarnings);
|
||||||
|
|
Loading…
Reference in a new issue