Enhance output of common FML errors in crash reports and server GUI.
This commit is contained in:
parent
c2f11ecc35
commit
ddcc6a1aa4
10 changed files with 146 additions and 15 deletions
|
@ -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,7 +30,7 @@ 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() {
|
||||
}
|
||||
|
@ -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.
|
||||
}
|
||||
|
|
|
@ -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<ModContainer, File> e : dupes.entries())
|
||||
{
|
||||
stream.println(String.format("\t%s : %s", e.getKey().getModId(), e.getValue().getAbsolutePath()));
|
||||
}
|
||||
stream.println("");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
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){}
|
||||
}
|
||||
|
|
|
@ -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<ArtifactVersion> 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("");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -59,6 +59,11 @@ public class EntitySpawnHandler extends SimpleChannelInboundHandler<FMLMessage.E
|
|||
{
|
||||
ModContainer mc = Loader.instance().getIndexedModList().get(spawnMsg.modId);
|
||||
EntityRegistration er = EntityRegistry.instance().lookupModSpawn(mc, spawnMsg.modEntityTypeId);
|
||||
if (er == null)
|
||||
{
|
||||
throw new RuntimeException( "Could not spawn mod entity ModID: " + spawnMsg.modId + " EntityID: " + spawnMsg.modEntityTypeId +
|
||||
" at ( " + spawnMsg.scaledX + "," + spawnMsg.scaledY + ", " + spawnMsg.scaledZ + ") Please contact mod author or server admin.");
|
||||
}
|
||||
WorldClient wc = FMLClientHandler.instance().getWorldClient();
|
||||
Class<? extends Entity> cls = er.getEntityClass();
|
||||
try
|
||||
|
@ -117,7 +122,7 @@ public class EntitySpawnHandler extends SimpleChannelInboundHandler<FMLMessage.E
|
|||
wc.addEntityToWorld(spawnMsg.entityId, entity);
|
||||
} catch (Exception e)
|
||||
{
|
||||
FMLLog.log(Level.ERROR, e, "A severe problem occurred during the spawning of an entity");
|
||||
FMLLog.log(Level.ERROR, e, "A severe problem occurred during the spawning of an entity at ( " + spawnMsg.scaledX + "," + spawnMsg.scaledY + ", " + spawnMsg.scaledZ +")");
|
||||
throw Throwables.propagate(e);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package cpw.mods.fml.common.registry;
|
|||
public class IncompatibleSubstitutionException extends RuntimeException {
|
||||
public IncompatibleSubstitutionException(String fromName, Object replacement, Object original)
|
||||
{
|
||||
super(String.format("The substitute %s for %s (type %s) is type incompatible.", replacement.getClass().getName(), fromName, original.getClass().getName()));
|
||||
}
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
|
Loading…
Reference in a new issue