Add in the ability for a client to throw a custom exception that displays a custom gui instead of the default error message.
This commit is contained in:
parent
a82285964f
commit
7327ea75f7
10 changed files with 165 additions and 6 deletions
|
@ -0,0 +1,43 @@
|
|||
package cpw.mods.fml.client;
|
||||
|
||||
import cpw.mods.fml.common.IFMLHandledException;
|
||||
import cpw.mods.fml.common.Side;
|
||||
import cpw.mods.fml.common.asm.SideOnly;
|
||||
import net.minecraft.src.FontRenderer;
|
||||
import net.minecraft.src.GuiErrorScreen;
|
||||
|
||||
/**
|
||||
* If a mod throws this exception during loading, it will be called back to render
|
||||
* the error screen through the methods below. This error will not be cleared, and will
|
||||
* not allow the game to carry on, but might be useful if your mod wishes to report
|
||||
* a fatal configuration error in a pretty way.
|
||||
*
|
||||
* Throw this through a proxy. It won't work on the dedicated server environment.
|
||||
* @author cpw
|
||||
*
|
||||
*/
|
||||
@SideOnly(Side.CLIENT)
|
||||
public abstract class CustomModLoadingErrorDisplayException extends RuntimeException implements IFMLHandledException
|
||||
{
|
||||
/**
|
||||
* Called after the GUI is inited by the parent code. You can do extra stuff here, maybe?
|
||||
*
|
||||
* @param errorScreen The error screen we're painting
|
||||
* @param fontRenderer A font renderer for you
|
||||
*/
|
||||
public abstract void initGui(GuiErrorScreen errorScreen, FontRenderer fontRenderer);
|
||||
|
||||
/**
|
||||
* Draw your error to the screen.
|
||||
*
|
||||
* <br/><em>Warning: Minecraft is in a deep error state.</em> <strong>All</strong> it can do is stop.
|
||||
* Do not try and do anything involving complex user interaction here.
|
||||
*
|
||||
* @param errorScreen The error screen to draw to
|
||||
* @param fontRenderer A font renderer for you
|
||||
* @param mouseRelX Mouse X
|
||||
* @param mouseRelY Mouse Y
|
||||
* @param tickTime tick time
|
||||
*/
|
||||
public abstract void drawScreen(GuiErrorScreen errorScreen, FontRenderer fontRenderer, int mouseRelX, int mouseRelY, float tickTime);
|
||||
}
|
|
@ -107,6 +107,8 @@ public class FMLClientHandler implements IFMLSidedHandler
|
|||
|
||||
private WrongMinecraftVersionException wrongMC;
|
||||
|
||||
private CustomModLoadingErrorDisplayException customError;
|
||||
|
||||
/**
|
||||
* Called to start the whole game off from
|
||||
* {@link MinecraftServer#startServer}
|
||||
|
@ -153,6 +155,11 @@ public class FMLClientHandler implements IFMLSidedHandler
|
|||
{
|
||||
modsMissing = missing;
|
||||
}
|
||||
catch (CustomModLoadingErrorDisplayException custom)
|
||||
{
|
||||
FMLLog.log(Level.SEVERE, custom, "A custom exception was thrown by a mod, the game will now halt");
|
||||
customError = custom;
|
||||
}
|
||||
catch (LoaderException le)
|
||||
{
|
||||
haltGame("There was a severe problem during mod loading that has caused the game to fail", le);
|
||||
|
@ -182,6 +189,12 @@ public class FMLClientHandler implements IFMLSidedHandler
|
|||
{
|
||||
Loader.instance().initializeMods();
|
||||
}
|
||||
catch (CustomModLoadingErrorDisplayException custom)
|
||||
{
|
||||
FMLLog.log(Level.SEVERE, custom, "A custom exception was thrown by a mod, the game will now halt");
|
||||
customError = custom;
|
||||
return;
|
||||
}
|
||||
catch (LoaderException le)
|
||||
{
|
||||
haltGame("There was a severe problem during mod loading that has caused the game to fail", le);
|
||||
|
@ -204,6 +217,10 @@ public class FMLClientHandler implements IFMLSidedHandler
|
|||
{
|
||||
client.func_71373_a(new GuiModsMissing(modsMissing));
|
||||
}
|
||||
else if (customError != null)
|
||||
{
|
||||
client.func_71373_a(new GuiCustomModLoadingErrorScreen(customError));
|
||||
}
|
||||
else
|
||||
{
|
||||
TextureFXManager.instance().loadTextures(client.field_71418_C.func_77292_e());
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
package cpw.mods.fml.client;
|
||||
|
||||
import cpw.mods.fml.common.Loader;
|
||||
import cpw.mods.fml.common.WrongMinecraftVersionException;
|
||||
import net.minecraft.src.GuiErrorScreen;
|
||||
|
||||
public class GuiCustomModLoadingErrorScreen extends GuiErrorScreen
|
||||
{
|
||||
private CustomModLoadingErrorDisplayException customException;
|
||||
public GuiCustomModLoadingErrorScreen(CustomModLoadingErrorDisplayException customException)
|
||||
{
|
||||
this.customException = customException;
|
||||
}
|
||||
@Override
|
||||
public void func_73866_w_()
|
||||
{
|
||||
super.func_73866_w_();
|
||||
this.customException.initGui(this, field_73886_k);
|
||||
}
|
||||
@Override
|
||||
public void func_73863_a(int p_73863_1_, int p_73863_2_, float p_73863_3_)
|
||||
{
|
||||
this.func_73873_v_();
|
||||
this.customException.drawScreen(this, field_73886_k, p_73863_1_, p_73863_2_, p_73863_3_);
|
||||
}
|
||||
}
|
|
@ -23,7 +23,7 @@ public class GuiModsMissing extends GuiErrorScreen
|
|||
public void func_73863_a(int p_73863_1_, int p_73863_2_, float p_73863_3_)
|
||||
{
|
||||
this.func_73873_v_();
|
||||
int offset = 85 - modsMissing.missingMods.size() * 10;
|
||||
int offset = Math.max(85 - modsMissing.missingMods.size() * 10, 10);
|
||||
this.func_73732_a(this.field_73886_k, "Forge Mod Loader has found a problem with your minecraft installation", this.field_73880_f / 2, offset, 0xFFFFFF);
|
||||
offset+=10;
|
||||
this.func_73732_a(this.field_73886_k, "The mods and versions listed below could not be found", this.field_73880_f / 2, offset, 0xFFFFFF);
|
||||
|
|
|
@ -35,7 +35,7 @@ public class GuiModsMissingForServer extends GuiScreen
|
|||
public void func_73863_a(int p_73863_1_, int p_73863_2_, float p_73863_3_)
|
||||
{
|
||||
this.func_73873_v_();
|
||||
int offset = 85 - modsMissing.getModList().size() * 10;
|
||||
int offset = Math.max(85 - modsMissing.getModList().size() * 10, 10);
|
||||
this.func_73732_a(this.field_73886_k, "Forge Mod Loader could not connect to this server", this.field_73880_f / 2, offset, 0xFFFFFF);
|
||||
offset += 10;
|
||||
this.func_73732_a(this.field_73886_k, "The mods and versions listed below could not be found", this.field_73880_f / 2, offset, 0xFFFFFF);
|
||||
|
|
6
fml/common/cpw/mods/fml/common/IFMLHandledException.java
Normal file
6
fml/common/cpw/mods/fml/common/IFMLHandledException.java
Normal file
|
@ -0,0 +1,6 @@
|
|||
package cpw.mods.fml.common;
|
||||
|
||||
public interface IFMLHandledException
|
||||
{
|
||||
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
package cpw.mods.fml.common;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
@ -88,6 +89,7 @@ public class LoadController
|
|||
state = state.transition(!errors.isEmpty());
|
||||
if (state != desiredState)
|
||||
{
|
||||
Throwable toThrow = null;
|
||||
FMLLog.severe("Fatal errors were detected during the transition from %s to %s. Loading cannot continue", oldState, desiredState);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
printModStates(sb);
|
||||
|
@ -96,10 +98,23 @@ public class LoadController
|
|||
for (Entry<String, Throwable> error : errors.entries())
|
||||
{
|
||||
FMLLog.log(Level.SEVERE, error.getValue(), "Caught exception from %s", error.getKey());
|
||||
if (error.getValue() instanceof IFMLHandledException)
|
||||
{
|
||||
toThrow = error.getValue();
|
||||
}
|
||||
else if (toThrow == null)
|
||||
{
|
||||
toThrow = error.getValue();
|
||||
}
|
||||
}
|
||||
if (toThrow != null && toThrow instanceof RuntimeException)
|
||||
{
|
||||
throw (RuntimeException)toThrow;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new LoaderException(toThrow);
|
||||
}
|
||||
|
||||
// Throw embedding the first error (usually the only one)
|
||||
throw new LoaderException(errors.values().iterator().next());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -158,7 +173,14 @@ public class LoadController
|
|||
|
||||
public void errorOccurred(ModContainer modContainer, Throwable exception)
|
||||
{
|
||||
errors.put(modContainer.getModId(), exception);
|
||||
if (exception instanceof InvocationTargetException)
|
||||
{
|
||||
errors.put(modContainer.getModId(), ((InvocationTargetException)exception).getCause());
|
||||
}
|
||||
else
|
||||
{
|
||||
errors.put(modContainer.getModId(), exception);
|
||||
}
|
||||
}
|
||||
|
||||
public void printModStates(StringBuilder ret)
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
package cpw.mods.mockmod;
|
||||
|
||||
import net.minecraft.src.GuiErrorScreen;
|
||||
import net.minecraft.src.ItemBlock;
|
||||
import net.minecraft.src.NetHandler;
|
||||
import net.minecraft.src.NetworkManager;
|
||||
import net.minecraft.src.Packet131MapData;
|
||||
import net.minecraft.src.Packet250CustomPayload;
|
||||
import net.minecraft.src.FontRenderer;
|
||||
import cpw.mods.fml.client.CustomModLoadingErrorDisplayException;
|
||||
import cpw.mods.fml.common.Mod;
|
||||
import cpw.mods.fml.common.Mod.Block;
|
||||
import cpw.mods.fml.common.Mod.Init;
|
||||
|
@ -12,6 +15,7 @@ import cpw.mods.fml.common.Mod.Instance;
|
|||
import cpw.mods.fml.common.Mod.Metadata;
|
||||
import cpw.mods.fml.common.Mod.PreInit;
|
||||
import cpw.mods.fml.common.Side;
|
||||
import cpw.mods.fml.common.SidedProxy;
|
||||
import cpw.mods.fml.common.asm.SideOnly;
|
||||
import cpw.mods.fml.common.event.FMLInitializationEvent;
|
||||
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
|
||||
|
@ -56,6 +60,8 @@ public class MockMod
|
|||
@Metadata
|
||||
private ModMetadata meta;
|
||||
|
||||
@SidedProxy(clientSide="cpw.mods.mockmod.MockProxyClient", serverSide="cpw.mods.mockmod.MockProxy")
|
||||
public static MockProxy proxy;
|
||||
// @Block(name="MyBlock", itemTypeClass=TestItem.class)
|
||||
// private MockBlock myBlock;
|
||||
|
||||
|
@ -70,5 +76,6 @@ public class MockMod
|
|||
public void init(FMLInitializationEvent evt)
|
||||
{
|
||||
System.out.printf("Hello from mockmod init : %s %s %s\n", myInstance, meta, MockBlock.tstInstance);
|
||||
proxy.throwError();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
package cpw.mods.mockmod;
|
||||
|
||||
public class MockProxy
|
||||
{
|
||||
public void throwError()
|
||||
{
|
||||
throw new RuntimeException();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package cpw.mods.mockmod;
|
||||
|
||||
import net.minecraft.src.FontRenderer;
|
||||
import net.minecraft.src.GuiErrorScreen;
|
||||
import cpw.mods.fml.client.CustomModLoadingErrorDisplayException;
|
||||
|
||||
public class MockProxyClient extends MockProxy
|
||||
{
|
||||
@Override
|
||||
public void throwError()
|
||||
{
|
||||
throw new CustomModLoadingErrorDisplayException()
|
||||
{
|
||||
|
||||
@Override
|
||||
public void drawScreen(GuiErrorScreen errorScreen, FontRenderer fontRenderer, int par1, int par2, float par3)
|
||||
{
|
||||
errorScreen.func_73732_a(fontRenderer, "MockMod doesn't like your installation", errorScreen.field_73880_f / 2, 75, 0xFFFFFF);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initGui(GuiErrorScreen errorScreen, FontRenderer renderer)
|
||||
{
|
||||
// noop
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue