diff --git a/fml/src/main/java/cpw/mods/fml/client/CustomModLoadingErrorDisplayException.java b/fml/src/main/java/cpw/mods/fml/client/CustomModLoadingErrorDisplayException.java index ffba8e51a..63f3b4092 100644 --- a/fml/src/main/java/cpw/mods/fml/client/CustomModLoadingErrorDisplayException.java +++ b/fml/src/main/java/cpw/mods/fml/client/CustomModLoadingErrorDisplayException.java @@ -14,6 +14,7 @@ package cpw.mods.fml.client; import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.gui.GuiErrorScreen; +import cpw.mods.fml.common.EnhancedRuntimeException; import cpw.mods.fml.common.IFMLHandledException; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; @@ -29,16 +30,16 @@ import cpw.mods.fml.relauncher.SideOnly; * */ @SideOnly(Side.CLIENT) -public abstract class CustomModLoadingErrorDisplayException extends RuntimeException implements IFMLHandledException +public abstract class CustomModLoadingErrorDisplayException extends EnhancedRuntimeException implements IFMLHandledException { public CustomModLoadingErrorDisplayException() { } - + public CustomModLoadingErrorDisplayException(String message, Throwable cause) { super(message, cause); } - + private static final long serialVersionUID = 1L; /** @@ -62,4 +63,6 @@ public abstract class CustomModLoadingErrorDisplayException extends RuntimeExcep * @param tickTime tick time */ public abstract void drawScreen(GuiErrorScreen errorScreen, FontRenderer fontRenderer, int mouseRelX, int mouseRelY, float tickTime); + + @Override public void printStackTrace(EnhancedRuntimeException.WrappedPrintStream s){}; // Do Nothing unless the modder wants to. } diff --git a/fml/src/main/java/cpw/mods/fml/common/DuplicateModsFoundException.java b/fml/src/main/java/cpw/mods/fml/common/DuplicateModsFoundException.java index f067605ff..25afefa76 100644 --- a/fml/src/main/java/cpw/mods/fml/common/DuplicateModsFoundException.java +++ b/fml/src/main/java/cpw/mods/fml/common/DuplicateModsFoundException.java @@ -13,6 +13,9 @@ package cpw.mods.fml.common; import java.io.File; +import java.util.Map.Entry; + +import cpw.mods.fml.common.EnhancedRuntimeException.WrappedPrintStream; import com.google.common.collect.SetMultimap; @@ -24,4 +27,14 @@ public class DuplicateModsFoundException extends LoaderException { this.dupes = dupes; } + @Override + protected void printStackTrace(WrappedPrintStream stream) + { + stream.println("Duplicate Mods:"); + for (Entry e : dupes.entries()) + { + stream.println(String.format("\t%s : %s", e.getKey().getModId(), e.getValue().getAbsolutePath())); + } + stream.println(""); + } } diff --git a/fml/src/main/java/cpw/mods/fml/common/EnhancedRuntimeException.java b/fml/src/main/java/cpw/mods/fml/common/EnhancedRuntimeException.java new file mode 100644 index 000000000..d039e0e8b --- /dev/null +++ b/fml/src/main/java/cpw/mods/fml/common/EnhancedRuntimeException.java @@ -0,0 +1,92 @@ +/* + * Forge Mod Loader + * Copyright (c) 2012-2016 Forge Dev LLC. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Lesser Public License v2.1 + * which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + */ +package cpw.mods.fml.common; + +import java.io.PrintStream; +import java.io.PrintWriter; +import java.io.StringWriter; + +/** + * RuntimeException that gives subclasses the simple opportunity to write extra data when printing the stack trace. + * Mainly a helper class as printsStackTrace has multiple signatures. + */ +public abstract class EnhancedRuntimeException extends RuntimeException +{ + private static final long serialVersionUID = 1L; + + public EnhancedRuntimeException() { super(); } + public EnhancedRuntimeException(String message) { super(message); } + public EnhancedRuntimeException(String message, Throwable cause) { super(message, cause); } + public EnhancedRuntimeException(Throwable cause) { super(cause); } + protected EnhancedRuntimeException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + } + + @Override + public String getMessage() + { + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + if (stack.length > 2 && stack[2].getClassName().startsWith("org.apache.logging.log4j.")) + { + // This is a bit of a hack to force ourselves to be able to give a extended description when log4j prints this out. + // Sadly this text is displayed AFTER the initial exception line, and before the stack trace. But as the intention + // is to print this to the end user this is what we need to do. + final StringWriter buf = new StringWriter(); + + String msg = super.getMessage(); + if (msg != null) + buf.append(msg); + + buf.append('\n'); + this.printStackTrace(new WrappedPrintStream() + { + @Override + void println(String line) + { + buf.append(line).append('\n'); + } + }); + return buf.toString(); + } + return super.getMessage(); + } + + @Override + public void printStackTrace(final PrintWriter s) + { + printStackTrace(new WrappedPrintStream() + { + @Override + void println(String line) + { + s.println(line); + } + }); + super.printStackTrace(s); + } + public void printStackTrace(final PrintStream s) + { + printStackTrace(new WrappedPrintStream() + { + @Override + void println(String line) + { + s.println(line); + } + }); + super.printStackTrace(s); + } + + protected abstract void printStackTrace(WrappedPrintStream stream); + + public static abstract class WrappedPrintStream + { + abstract void println(String line); + } +} diff --git a/fml/src/main/java/cpw/mods/fml/common/ILanguageAdapter.java b/fml/src/main/java/cpw/mods/fml/common/ILanguageAdapter.java index 11921ad6f..f40d49a33 100644 --- a/fml/src/main/java/cpw/mods/fml/common/ILanguageAdapter.java +++ b/fml/src/main/java/cpw/mods/fml/common/ILanguageAdapter.java @@ -96,7 +96,7 @@ public interface ILanguageAdapter { // If we come here we could not find a setter for this proxy. FMLLog.severe("Failed loading proxy into %s.%s, could not find setter function. Did you declare the field with 'val' instead of 'var'?", proxyTarget.getSimpleName(), target.getName()); - throw new LoaderException(); + throw new LoaderException(String.format("Failed loading proxy into %s.%s, could not find setter function. Did you declare the field with 'val' instead of 'var'?", proxyTarget.getSimpleName(), target.getName())); } @Override @@ -141,7 +141,7 @@ public interface ILanguageAdapter { if (!target.getType().isAssignableFrom(proxy.getClass())) { FMLLog.severe("Attempted to load a proxy type %s into %s.%s, but the types don't match", targetType, proxyTarget.getSimpleName(), target.getName()); - throw new LoaderException(); + throw new LoaderException(String.format("Attempted to load a proxy type %s into %s.%s, but the types don't match", targetType, proxyTarget.getSimpleName(), target.getName())); } setProxy(target, proxyTarget, proxy); diff --git a/fml/src/main/java/cpw/mods/fml/common/Loader.java b/fml/src/main/java/cpw/mods/fml/common/Loader.java index 86c48abb7..6469c4764 100644 --- a/fml/src/main/java/cpw/mods/fml/common/Loader.java +++ b/fml/src/main/java/cpw/mods/fml/common/Loader.java @@ -182,7 +182,7 @@ public class Loader if (!mccversion.equals(MC_VERSION)) { FMLLog.severe("This version of FML is built for Minecraft %s, we have detected Minecraft %s in your minecraft jar file", mccversion, MC_VERSION); - throw new LoaderException(); + throw new LoaderException(String.format("This version of FML is built for Minecraft %s, we have detected Minecraft %s in your minecraft jar file", mccversion, MC_VERSION)); } minecraft = new MinecraftDummyContainer(MC_VERSION); @@ -418,7 +418,7 @@ public class Loader if (!dirMade) { FMLLog.severe("Unable to create the mod directory %s", canonicalModsPath); - throw new LoaderException(); + throw new LoaderException(String.format("Unable to create the mod directory %s", canonicalModsPath)); } FMLLog.info("Mod directory created successfully"); } @@ -676,7 +676,7 @@ public class Loader if (parseFailure) { FMLLog.log(Level.WARN, "Unable to parse dependency string %s", dependencyString); - throw new LoaderException(); + throw new LoaderException(String.format("Unable to parse dependency string %s", dependencyString)); } } diff --git a/fml/src/main/java/cpw/mods/fml/common/LoaderException.java b/fml/src/main/java/cpw/mods/fml/common/LoaderException.java index 3a0adbf72..2d236d5a4 100644 --- a/fml/src/main/java/cpw/mods/fml/common/LoaderException.java +++ b/fml/src/main/java/cpw/mods/fml/common/LoaderException.java @@ -5,14 +5,14 @@ * are made available under the terms of the GNU Lesser Public License v2.1 * which accompanies this distribution, and is available at * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html - * + * * Contributors: * cpw - implementation */ package cpw.mods.fml.common; -public class LoaderException extends RuntimeException +public class LoaderException extends EnhancedRuntimeException { /** * @@ -27,4 +27,10 @@ public class LoaderException extends RuntimeException public LoaderException() { } + public LoaderException(String message) + { + super(message); + } + + @Override protected void printStackTrace(WrappedPrintStream stream){} } diff --git a/fml/src/main/java/cpw/mods/fml/common/MissingModsException.java b/fml/src/main/java/cpw/mods/fml/common/MissingModsException.java index a2b50256b..87e4f5feb 100644 --- a/fml/src/main/java/cpw/mods/fml/common/MissingModsException.java +++ b/fml/src/main/java/cpw/mods/fml/common/MissingModsException.java @@ -16,7 +16,7 @@ import java.util.Set; import cpw.mods.fml.common.versioning.ArtifactVersion; -public class MissingModsException extends RuntimeException +public class MissingModsException extends EnhancedRuntimeException { private static final long serialVersionUID = 1L; public final Set missingMods; @@ -25,4 +25,15 @@ public class MissingModsException extends RuntimeException { this.missingMods = missingMods; } + + @Override + protected void printStackTrace(WrappedPrintStream stream) + { + stream.println("Missing Mods:"); + for (ArtifactVersion v : missingMods) + { + stream.println(String.format("\t%s : %s", v.getLabel(), v.getRangeString())); + } + stream.println(""); + } } diff --git a/fml/src/main/java/cpw/mods/fml/common/ProxyInjector.java b/fml/src/main/java/cpw/mods/fml/common/ProxyInjector.java index 473900739..10d94335f 100644 --- a/fml/src/main/java/cpw/mods/fml/common/ProxyInjector.java +++ b/fml/src/main/java/cpw/mods/fml/common/ProxyInjector.java @@ -45,7 +45,7 @@ public class ProxyInjector { // Impossible? FMLLog.severe("Attempted to load a proxy type into %s.%s but the field was not found", targ.getClassName(), targ.getObjectName()); - throw new LoaderException(); + throw new LoaderException(String.format("Attempted to load a proxy type into %s.%s but the field was not found", targ.getClassName(), targ.getObjectName())); } target.setAccessible(true); @@ -61,12 +61,12 @@ public class ProxyInjector if (languageAdapter.supportsStatics() && (target.getModifiers() & Modifier.STATIC) == 0 ) { FMLLog.severe("Attempted to load a proxy type %s into %s.%s, but the field is not static", targetType, targ.getClassName(), targ.getObjectName()); - throw new LoaderException(); + throw new LoaderException(String.format("Attempted to load a proxy type %s into %s.%s, but the field is not static", targetType, targ.getClassName(), targ.getObjectName())); } if (!target.getType().isAssignableFrom(proxy.getClass())) { FMLLog.severe("Attempted to load a proxy type %s into %s.%s, but the types don't match", targetType, targ.getClassName(), targ.getObjectName()); - throw new LoaderException(); + throw new LoaderException(String.format("Attempted to load a proxy type %s into %s.%s, but the types don't match", targetType, targ.getClassName(), targ.getObjectName())); } languageAdapter.setProxy(target, proxyTarget, proxy); } diff --git a/fml/src/main/java/cpw/mods/fml/common/network/internal/EntitySpawnHandler.java b/fml/src/main/java/cpw/mods/fml/common/network/internal/EntitySpawnHandler.java index 450d1cf2a..65acc9543 100644 --- a/fml/src/main/java/cpw/mods/fml/common/network/internal/EntitySpawnHandler.java +++ b/fml/src/main/java/cpw/mods/fml/common/network/internal/EntitySpawnHandler.java @@ -59,6 +59,11 @@ public class EntitySpawnHandler extends SimpleChannelInboundHandler cls = er.getEntityClass(); try @@ -117,7 +122,7 @@ public class EntitySpawnHandler extends SimpleChannelInboundHandler