Merge pull request #597 from RainWarrior/blame
Added blaming of coremods and mods not targetting Java 6
This commit is contained in:
commit
c85aa9351a
10 changed files with 525 additions and 8 deletions
|
@ -8,3 +8,12 @@
|
|||
}
|
||||
|
||||
public String func_71501_a()
|
||||
@@ -220,6 +221,8 @@
|
||||
{
|
||||
StringBuilder stringbuilder = new StringBuilder();
|
||||
stringbuilder.append("---- Minecraft Crash Report ----\n");
|
||||
+ net.minecraftforge.fml.common.asm.transformers.BlamingTransformer.onCrash(stringbuilder);
|
||||
+ net.minecraftforge.fml.relauncher.CoreModManager.onCrash(stringbuilder);
|
||||
stringbuilder.append("// ");
|
||||
stringbuilder.append(func_71503_h());
|
||||
stringbuilder.append("\n\n");
|
||||
|
|
|
@ -55,6 +55,7 @@ import net.minecraftforge.fml.common.gameevent.PlayerEvent;
|
|||
import net.minecraftforge.fml.common.gameevent.TickEvent;
|
||||
import net.minecraftforge.fml.common.gameevent.TickEvent.Phase;
|
||||
import net.minecraftforge.fml.common.network.NetworkRegistry;
|
||||
import net.minecraftforge.fml.relauncher.CoreModManager;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.server.FMLServerHandler;
|
||||
|
||||
|
@ -107,6 +108,28 @@ public class FMLCommonHandler
|
|||
private WeakReference<SaveHandler> handlerToCheck;
|
||||
private EventBus eventBus = new EventBus();
|
||||
private volatile CountDownLatch exitLatch = null;
|
||||
|
||||
private FMLCommonHandler()
|
||||
{
|
||||
registerCrashCallable(new ICrashCallable()
|
||||
{
|
||||
public String call() throws Exception
|
||||
{
|
||||
StringBuilder builder = new StringBuilder();
|
||||
Joiner joiner = Joiner.on("\n ");
|
||||
for(String coreMod : CoreModManager.getTransformers().keySet())
|
||||
{
|
||||
builder.append("\n" + coreMod + "\n ").append(joiner.join(CoreModManager.getTransformers().get(coreMod)));
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
public String getLabel()
|
||||
{
|
||||
return "Loaded coremods (and transformers)";
|
||||
}
|
||||
});
|
||||
}
|
||||
/**
|
||||
* The FML event bus. Subscribe here for FML related events
|
||||
*
|
||||
|
|
|
@ -27,6 +27,7 @@ import java.util.Set;
|
|||
|
||||
import net.minecraftforge.fml.common.Mod.Instance;
|
||||
import net.minecraftforge.fml.common.Mod.Metadata;
|
||||
import net.minecraftforge.fml.common.asm.transformers.BlamingTransformer;
|
||||
import net.minecraftforge.fml.common.discovery.ASMDataTable;
|
||||
import net.minecraftforge.fml.common.discovery.ModCandidate;
|
||||
import net.minecraftforge.fml.common.discovery.ASMDataTable.ASMData;
|
||||
|
@ -416,6 +417,7 @@ public class FMLModContainer implements ModContainer
|
|||
{
|
||||
try
|
||||
{
|
||||
BlamingTransformer.addClasses(getModId(), candidate.getClassList());
|
||||
ModClassLoader modClassLoader = event.getModClassLoader();
|
||||
modClassLoader.addFile(source);
|
||||
modClassLoader.clearNegativeCacheFor(candidate.getClassList());
|
||||
|
|
|
@ -14,19 +14,21 @@ package net.minecraftforge.fml.common;
|
|||
|
||||
import java.io.File;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.logging.log4j.Level;
|
||||
|
||||
import net.minecraft.launchwrapper.IClassTransformer;
|
||||
import net.minecraft.launchwrapper.LaunchClassLoader;
|
||||
import net.minecraftforge.fml.common.asm.transformers.ModAPITransformer;
|
||||
import net.minecraftforge.fml.common.discovery.ASMDataTable;
|
||||
|
||||
import org.apache.logging.log4j.Level;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
/**
|
||||
|
@ -59,15 +61,18 @@ public class ModClassLoader extends URLClassLoader
|
|||
}
|
||||
|
||||
public File[] getParentSources() {
|
||||
List<URL> urls=mainClassLoader.getSources();
|
||||
File[] sources=new File[urls.size()];
|
||||
try
|
||||
{
|
||||
for (int i = 0; i<urls.size(); i++)
|
||||
List<File> files=new ArrayList<File>();
|
||||
for(URL url : mainClassLoader.getSources())
|
||||
{
|
||||
sources[i]=new File(urls.get(i).toURI());
|
||||
URI uri = url.toURI();
|
||||
if(uri.getScheme() == "file")
|
||||
{
|
||||
files.add(new File(uri));
|
||||
}
|
||||
}
|
||||
return sources;
|
||||
return files.toArray(new File[]{});
|
||||
}
|
||||
catch (URISyntaxException e)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,263 @@
|
|||
|
||||
|
||||
package net.minecraftforge.fml.common.asm;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.net.URLStreamHandler;
|
||||
import java.security.Permission;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import net.minecraft.launchwrapper.IClassTransformer;
|
||||
import net.minecraft.launchwrapper.LaunchClassLoader;
|
||||
|
||||
import org.objectweb.asm.ClassVisitor;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.FieldVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.Type;
|
||||
import org.objectweb.asm.commons.GeneratorAdapter;
|
||||
import org.objectweb.asm.commons.Method;
|
||||
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
public class ASMTransformerWrapper
|
||||
{
|
||||
private static final Map<String, String> wrapperModMap = Maps.newHashMap();
|
||||
private static final Map<String, String> wrapperParentMap = Maps.newHashMap();
|
||||
|
||||
private static final LoadingCache<String, byte[]> wrapperCache = CacheBuilder.newBuilder()
|
||||
.maximumSize(30)
|
||||
.weakValues()
|
||||
.build(new CacheLoader<String, byte[]>()
|
||||
{
|
||||
public byte[] load(String file) throws Exception
|
||||
{
|
||||
return makeWrapper(file);
|
||||
}
|
||||
});
|
||||
|
||||
private static final URL asmGenRoot;
|
||||
private static boolean injected = false;
|
||||
|
||||
static
|
||||
{
|
||||
try
|
||||
{
|
||||
asmGenRoot = new URL("asmgen", null, -1, "/", new ASMGenHandler());
|
||||
}
|
||||
catch(MalformedURLException e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static class ASMGenHandler extends URLStreamHandler
|
||||
{
|
||||
protected URLConnection openConnection(URL url) throws IOException
|
||||
{
|
||||
String file = url.getFile();
|
||||
if(file.equals("/"))
|
||||
{
|
||||
return new URLConnection(url)
|
||||
{
|
||||
public void connect() throws IOException
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
};
|
||||
}
|
||||
if(!file.startsWith("/")) throw new RuntimeException("Malformed URL: " + url);
|
||||
file = file.substring(1);
|
||||
if(wrapperModMap.containsKey(file))
|
||||
{
|
||||
return new ASMGenConnection(url, file);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static class ASMGenConnection extends URLConnection
|
||||
{
|
||||
private final String file;
|
||||
|
||||
protected ASMGenConnection(URL url, String file)
|
||||
{
|
||||
super(url);
|
||||
this.file = file;
|
||||
}
|
||||
|
||||
public void connect() throws IOException
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getInputStream()
|
||||
{
|
||||
try
|
||||
{
|
||||
return new ByteArrayInputStream(wrapperCache.get(file));
|
||||
}
|
||||
catch (ExecutionException e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Permission getPermission()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static String getTransformerWrapper(LaunchClassLoader launchLoader, String parentClass, String coreMod)
|
||||
{
|
||||
if(!injected)
|
||||
{
|
||||
injected = true;
|
||||
launchLoader.addURL(asmGenRoot);
|
||||
}
|
||||
|
||||
String name = getWrapperName(parentClass);
|
||||
String fileName = name.replace('.', '/') + ".class";
|
||||
wrapperModMap.put(fileName, coreMod);
|
||||
wrapperParentMap.put(fileName, parentClass);
|
||||
return name;
|
||||
}
|
||||
|
||||
private static byte[] makeWrapper(String fileName)
|
||||
{
|
||||
if(!wrapperModMap.containsKey(fileName) || !wrapperParentMap.containsKey(fileName) || !fileName.endsWith(".class"))
|
||||
{
|
||||
throw new IllegalArgumentException("makeWrapper called with strange argument: " + fileName);
|
||||
}
|
||||
String name = fileName.substring(0, fileName.length() - ".class".length());
|
||||
|
||||
try
|
||||
{
|
||||
Type wrapper = Type.getType(TransformerWrapper.class);
|
||||
|
||||
ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
|
||||
|
||||
writer.visit(Opcodes.V1_6, Opcodes.ACC_PUBLIC, name, null, wrapper.getInternalName(), null);
|
||||
|
||||
Method m = Method.getMethod("void <init> ()");
|
||||
GeneratorAdapter mg = new GeneratorAdapter(Opcodes.ACC_PUBLIC, m, null, null, writer);
|
||||
mg.loadThis();
|
||||
mg.invokeConstructor(wrapper, m);
|
||||
mg.returnValue();
|
||||
mg.endMethod();
|
||||
|
||||
m = Method.getMethod("java.lang.String getParentClass ()");
|
||||
mg = new GeneratorAdapter(Opcodes.ACC_PROTECTED, m, null, null, writer);
|
||||
mg.push(wrapperParentMap.get(fileName));
|
||||
mg.returnValue();
|
||||
mg.endMethod();
|
||||
|
||||
m = Method.getMethod("java.lang.String getCoreMod ()");
|
||||
mg = new GeneratorAdapter(Opcodes.ACC_PROTECTED, m, null, null, writer);
|
||||
mg.push(wrapperModMap.get(fileName));
|
||||
mg.returnValue();
|
||||
mg.endMethod();
|
||||
|
||||
writer.visitEnd();
|
||||
|
||||
return writer.toByteArray();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static String getWrapperName(String parentClass)
|
||||
{
|
||||
return parentClass + "_$Wrapper";
|
||||
}
|
||||
|
||||
private static class WrapperVisitor extends ClassVisitor
|
||||
{
|
||||
private final String name;
|
||||
private final String parentClass;
|
||||
|
||||
public WrapperVisitor(ClassVisitor cv, String name, String parentClass)
|
||||
{
|
||||
super(Opcodes.ASM5, cv);
|
||||
this.name = name.replace('.', '/');
|
||||
this.parentClass = parentClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces)
|
||||
{
|
||||
super.visit(version, access, this.name, signature, superName, interfaces);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FieldVisitor visitField(int access, String name, String desc, String signature, Object value)
|
||||
{
|
||||
if(name.equals("parentClass"))
|
||||
{
|
||||
return super.visitField(access, name, desc, signature, parentClass);
|
||||
}
|
||||
return super.visitField(access, name, desc, signature, value);
|
||||
}
|
||||
}
|
||||
|
||||
public static abstract class TransformerWrapper implements IClassTransformer
|
||||
{
|
||||
private final IClassTransformer parent;
|
||||
|
||||
public TransformerWrapper()
|
||||
{
|
||||
try
|
||||
{
|
||||
this.parent = (IClassTransformer)this.getClass().getClassLoader().loadClass(getParentClass()).newInstance();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] transform(String name, String transformedName, byte[] basicClass)
|
||||
{
|
||||
try
|
||||
{
|
||||
return parent.transform(name, transformedName, basicClass);
|
||||
}
|
||||
catch(Throwable e)
|
||||
{
|
||||
throw new TransformerException("Exception in class transformer " + parent + " from coremod " + getCoreMod(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "TransformerWrapper(" + getParentClass() + ", " + getCoreMod() + ")";
|
||||
}
|
||||
|
||||
protected abstract String getParentClass();
|
||||
|
||||
protected abstract String getCoreMod();
|
||||
}
|
||||
|
||||
static class TransformerException extends RuntimeException
|
||||
{
|
||||
public TransformerException(String message, Throwable cause)
|
||||
{
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,119 @@
|
|||
package net.minecraftforge.fml.common.asm.transformers;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import net.minecraft.launchwrapper.IClassTransformer;
|
||||
import net.minecraftforge.fml.common.FMLLog;
|
||||
|
||||
import org.apache.commons.lang3.JavaVersion;
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
import org.objectweb.asm.ClassReader;
|
||||
import org.objectweb.asm.ClassVisitor;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
public class BlamingTransformer implements IClassTransformer
|
||||
{
|
||||
private static final Map<String, String> classMap = new HashMap<String, String>();
|
||||
private static final Set<String> naughtyMods = new HashSet<String>();
|
||||
private static final Set<String> naughtyClasses = new TreeSet<String>();
|
||||
private static final Set<String> orphanNaughtyClasses = new HashSet();
|
||||
|
||||
@Override
|
||||
public byte[] transform(String name, String transformedName, byte[] bytes)
|
||||
{
|
||||
if (bytes == null) { return null; }
|
||||
|
||||
ClassReader classReader = new ClassReader(bytes);
|
||||
VersionVisitor visitor = new VersionVisitor();
|
||||
classReader.accept(visitor, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
public static void blame(String modId, String cls)
|
||||
{
|
||||
naughtyClasses.add(cls);
|
||||
naughtyMods.add(modId);
|
||||
FMLLog.severe("Unsupported class format in mod %s: class %s", modId, cls);
|
||||
}
|
||||
|
||||
public static class VersionVisitor extends ClassVisitor
|
||||
{
|
||||
public VersionVisitor()
|
||||
{
|
||||
super(Opcodes.ASM5);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces)
|
||||
{
|
||||
if( (version == Opcodes.V1_8 && !SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_1_8)) ||
|
||||
(version == Opcodes.V1_7 && !SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_1_7)) )
|
||||
{
|
||||
if(classMap.containsKey(name)) blame(classMap.get(name), name);
|
||||
else orphanNaughtyClasses.add(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkPendingNaughty()
|
||||
{
|
||||
ImmutableSet.Builder<String> toRemove = ImmutableSet.builder();
|
||||
for(String cls : orphanNaughtyClasses)
|
||||
{
|
||||
if(classMap.containsKey(cls))
|
||||
{
|
||||
String modId = classMap.get(cls);
|
||||
blame(modId, cls);
|
||||
toRemove.add(cls);
|
||||
}
|
||||
}
|
||||
orphanNaughtyClasses.removeAll(toRemove.build());
|
||||
}
|
||||
|
||||
public static void addClasses(String modId, Set<String> classList)
|
||||
{
|
||||
for(String cls : classList)
|
||||
{
|
||||
classMap.put(cls, modId);
|
||||
}
|
||||
checkPendingNaughty();
|
||||
}
|
||||
|
||||
public static void onCrash(StringBuilder builder)
|
||||
{
|
||||
checkPendingNaughty();
|
||||
if(!naughtyClasses.isEmpty())
|
||||
{
|
||||
builder.append("\n*** ATTENTION: detected classes with unsupported format ***\n");
|
||||
builder.append("*** DO NOT SUBMIT THIS CRASH REPORT TO FORGE ***\n\n");
|
||||
if(!naughtyMods.isEmpty())
|
||||
{
|
||||
builder.append("Contact authors of the following mods: \n");
|
||||
for(String modId : naughtyMods)
|
||||
{
|
||||
builder.append(" ").append(modId).append("\n");
|
||||
}
|
||||
}
|
||||
if(!orphanNaughtyClasses.isEmpty())
|
||||
{
|
||||
builder.append("Unidentified unsupported classes: \n");
|
||||
for(String cls : orphanNaughtyClasses)
|
||||
{
|
||||
builder.append(" ").append(cls).append("\n");
|
||||
}
|
||||
}
|
||||
builder.append('\n');
|
||||
}
|
||||
}
|
||||
}
|
|
@ -25,6 +25,7 @@ import java.util.Comparator;
|
|||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.jar.Attributes;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
|
@ -32,6 +33,7 @@ import net.minecraft.launchwrapper.ITweaker;
|
|||
import net.minecraft.launchwrapper.Launch;
|
||||
import net.minecraft.launchwrapper.LaunchClassLoader;
|
||||
import net.minecraftforge.fml.common.FMLLog;
|
||||
import net.minecraftforge.fml.common.asm.ASMTransformerWrapper;
|
||||
import net.minecraftforge.fml.common.asm.transformers.ModAccessTransformer;
|
||||
import net.minecraftforge.fml.common.launcher.FMLInjectionAndSortingTweaker;
|
||||
import net.minecraftforge.fml.common.launcher.FMLTweaker;
|
||||
|
@ -50,6 +52,7 @@ import com.google.common.collect.ImmutableList;
|
|||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.ObjectArrays;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.primitives.Ints;
|
||||
|
||||
public class CoreModManager {
|
||||
|
@ -58,12 +61,22 @@ public class CoreModManager {
|
|||
private static final Attributes.Name MODSIDE = new Attributes.Name("ModSide");
|
||||
private static String[] rootPlugins = { "net.minecraftforge.fml.relauncher.FMLCorePlugin", "net.minecraftforge.classloading.FMLForgePlugin" };
|
||||
private static List<String> loadedCoremods = Lists.newArrayList();
|
||||
private static Map<String, List<String>> transformers = Maps.newHashMap();
|
||||
private static List<FMLPluginWrapper> loadPlugins;
|
||||
private static boolean deobfuscatedEnvironment;
|
||||
private static FMLTweaker tweaker;
|
||||
private static File mcDir;
|
||||
private static List<String> reparsedCoremods = Lists.newArrayList();
|
||||
private static List<String> accessTransformers = Lists.newArrayList();
|
||||
private static Set<String> rootNames = Sets.newHashSet();
|
||||
|
||||
static
|
||||
{
|
||||
for(String cls : rootPlugins)
|
||||
{
|
||||
rootNames.add(cls.substring(cls.lastIndexOf('.') + 1));
|
||||
}
|
||||
}
|
||||
|
||||
private static class FMLPluginWrapper implements ITweaker {
|
||||
public final String name;
|
||||
|
@ -98,10 +111,19 @@ public class CoreModManager {
|
|||
public void injectIntoClassLoader(LaunchClassLoader classLoader)
|
||||
{
|
||||
FMLRelaunchLog.fine("Injecting coremod %s {%s} class transformers", name, coreModInstance.getClass().getName());
|
||||
List<String> ts = Lists.newArrayList();
|
||||
if (coreModInstance.getASMTransformerClass() != null) for (String transformer : coreModInstance.getASMTransformerClass())
|
||||
{
|
||||
FMLRelaunchLog.finer("Registering transformer %s", transformer);
|
||||
classLoader.registerTransformer(transformer);
|
||||
classLoader.registerTransformer(ASMTransformerWrapper.getTransformerWrapper(classLoader, transformer, name));
|
||||
ts.add(transformer);
|
||||
}
|
||||
if(!rootNames.contains(name))
|
||||
{
|
||||
String loc;
|
||||
if(location == null) loc = "unknown";
|
||||
else loc = location.getName();
|
||||
transformers.put(name + " (" + loc + ")", ts);
|
||||
}
|
||||
FMLRelaunchLog.fine("Injection complete");
|
||||
|
||||
|
@ -405,6 +427,11 @@ public class CoreModManager {
|
|||
return loadedCoremods;
|
||||
}
|
||||
|
||||
public static Map<String, List<String>> getTransformers()
|
||||
{
|
||||
return transformers;
|
||||
}
|
||||
|
||||
public static List<String> getReparseableCoremods()
|
||||
{
|
||||
return reparsedCoremods;
|
||||
|
@ -609,4 +636,17 @@ public class CoreModManager {
|
|||
{
|
||||
return accessTransformers;
|
||||
}
|
||||
|
||||
public static void onCrash(StringBuilder builder)
|
||||
{
|
||||
if(!loadedCoremods.isEmpty() || !reparsedCoremods.isEmpty())
|
||||
{
|
||||
builder.append("\nWARNING: coremods are present:\n");
|
||||
for(String coreMod : transformers.keySet())
|
||||
{
|
||||
builder.append(" ").append(coreMod).append('\n');
|
||||
}
|
||||
builder.append("Contact their authors BEFORE contacting forge\n\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ public class FMLCorePlugin implements IFMLLoadingPlugin
|
|||
public String[] getASMTransformerClass()
|
||||
{
|
||||
return new String[] {
|
||||
"net.minecraftforge.fml.common.asm.transformers.BlamingTransformer",
|
||||
"net.minecraftforge.fml.common.asm.transformers.MarkerTransformer",
|
||||
"net.minecraftforge.fml.common.asm.transformers.SideTransformer",
|
||||
"net.minecraftforge.fml.common.asm.transformers.EventSubscriptionTransformer",
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
package net.minecraftforge.fml.debug;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import net.minecraft.launchwrapper.IClassTransformer;
|
||||
import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin;
|
||||
|
||||
public class FaultyCoreMod implements IFMLLoadingPlugin {
|
||||
public static boolean enabled = false;
|
||||
|
||||
public String[] getASMTransformerClass()
|
||||
{
|
||||
return new String[] { FaultyTransformer.class.getName() };
|
||||
}
|
||||
|
||||
public String getModContainerClass() { return null; }
|
||||
public String getSetupClass() { return null; }
|
||||
public void injectData(Map<String, Object> data) {}
|
||||
public String getAccessTransformerClass() { return null; }
|
||||
|
||||
public static class FaultyTransformer implements IClassTransformer {
|
||||
|
||||
public byte[] transform(String name, String transformedName, byte[] basicClass)
|
||||
{
|
||||
if(enabled && name.equals("net.minecraft.client.gui.GuiMainMenu")) throw new RuntimeException("Faulty transformer test exception");
|
||||
return basicClass;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
/*package net.minecraftforge.fml.debug;
|
||||
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.common.Mod.EventHandler;
|
||||
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
|
||||
|
||||
@Mod(modid = Java8Debug.MODID, version = Java8Debug.VERSION)
|
||||
public class Java8Debug implements ITest
|
||||
{
|
||||
public static final String MODID = "Java8Debug";
|
||||
public static final String VERSION = "1.0";
|
||||
|
||||
@EventHandler
|
||||
public void init(FMLInitializationEvent event)
|
||||
{
|
||||
System.out.println("Java8Debug mod loaded");
|
||||
}
|
||||
}
|
||||
|
||||
interface ITest
|
||||
{
|
||||
default int test()
|
||||
{
|
||||
return 42;
|
||||
}
|
||||
}*/
|
Loading…
Reference in a new issue