package gq.malwarefight.nosession.relaunch; import gq.malwarefight.nosession.tweaks.CleanupTweaker; import gq.malwarefight.nosession.utils.Utils; import net.minecraft.launchwrapper.Launch; import net.minecraftforge.fml.client.FMLClientHandler; import net.minecraftforge.fml.common.Loader; import net.minecraftforge.fml.common.ModAPIManager; import net.minecraftforge.fml.common.asm.ASMTransformerWrapper; import net.minecraftforge.fml.common.registry.ItemStackHolderInjector; import net.minecraftforge.fml.common.registry.ObjectHolderRegistry; import net.minecraftforge.fml.relauncher.FMLInjectionData; import net.minecraftforge.fml.relauncher.FMLLaunchHandler; import java.io.File; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; public class Relaunch { public static void relaunch(ArrayList args, File gameDir, File assetsDir, String version) throws Exception { resetSecurityManager(); setToNull(FMLLaunchHandler.class, "INSTANCE"); setToNull(Loader.class, "instance"); setToNull(ModAPIManager.class, "INSTANCE"); setToNull(ObjectHolderRegistry.class, "INSTANCE"); setToNull(ItemStackHolderInjector.class, "INSTANCE"); setToNull(FMLClientHandler.class, "INSTANCE"); setToNull(Loader.class, "injectedContainers"); Utils.setStaticValue(FMLInjectionData.class, "containers", new ArrayList()); resetClass(ASMTransformerWrapper.class); URLClassLoader originalClassLoader = (URLClassLoader) Launch.class.getClassLoader(); URL[] newURLS = new URL[originalClassLoader.getURLs().length + 1]; URLClassLoader lcl = new URLClassLoader(newURLS, originalClassLoader); //noinspection unchecked Class innerLaunch = (Class) Class.forName("net.minecraft.launchwrapper.Launch", false, lcl); Method launch = innerLaunch.getDeclaredMethod("main", String[].class); launch.invoke(null, (Object) constructArgs(args, gameDir, assetsDir, version)); } public static String[] constructArgs(ArrayList initial, File gameDir, File assetDir, String version) { initial.add("--version"); initial.add(version); initial.add("--gameDir"); initial.add(gameDir.getAbsolutePath()); initial.add("--assetsDir"); initial.add(assetDir.getAbsolutePath()); initial.add("--tweakClass"); initial.add("gq.malwarefight.nosession.tweaks.CleanupTweaker"); return initial.toArray(new String[0]); } public static void resetSecurityManager() throws IllegalAccessException, NoSuchMethodException, InvocationTargetException { Method m = Class.class.getDeclaredMethod("getDeclaredFields0", boolean.class); m.setAccessible(true); Field[] fields = (Field[]) m.invoke(System.class, false); for (Field field: fields) { if (field.getType().equals(SecurityManager.class)) { field.setAccessible(true); field.set(null, null); } } } public static void resetClass(Class cls) throws IllegalAccessException, NoSuchFieldException { Field[] fields = cls.getDeclaredFields(); for (Field field: fields) { if ((field.getModifiers() & Modifier.STATIC) != 0) { setToNull(field); } } } public static void setToNull(Class cls, String fieldname) throws NoSuchFieldException, IllegalAccessException { Field f = cls.getDeclaredField(fieldname); setToNull(f); } public static void setToNull(Field f) throws IllegalAccessException, NoSuchFieldException { f.setAccessible(true); if ((f.getModifiers() & Modifier.FINAL) != 0) { // if it is final Field modifiers = Field.class.getDeclaredField("modifiers"); modifiers.setAccessible(true); int value = modifiers.getInt(f); value &= ~Modifier.FINAL; modifiers.setInt(f, value); } if (f.getGenericType().equals(Boolean.TYPE)) { f.set(null, false); } else { f.set(null, null); } } }