aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/gq/malwarefight/nosession/relaunch/Relaunch.java
blob: e712254cf18669afb2d44857541f73e4d1a1782e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
package gq.malwarefight.nosession.relaunch;

import gq.malwarefight.nosession.tweaks.cleanup.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.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;

public class Relaunch {
    public static void relaunch(ArrayList<String> 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<String>());
        resetTransformerWrapper();
        addSelfToClassloader();
        Class<Launch> innerLaunch = Launch.class;
        Method launch = innerLaunch.getDeclaredMethod("main", String[].class);
        launch.invoke(null, (Object) constructArgs(args, gameDir, assetsDir, version));
    }

    private static String[] constructArgs(ArrayList<String> 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(CleanupTweaker.class.getName());
        return initial.toArray(new String[0]);
    }

    private 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);
            }
        }
    }


    private static void resetTransformerWrapper() throws IllegalAccessException, NoSuchFieldException {
        Field[] fields = ASMTransformerWrapper.class.getDeclaredFields();
        for (Field field: fields) {
            if ((field.getModifiers() & Modifier.STATIC) != 0) {
                setToNull(field);
            }
        }
    }

    private static void setToNull(Class<?> cls, String fieldname) throws NoSuchFieldException, IllegalAccessException {
        Field f = cls.getDeclaredField(fieldname);
        setToNull(f);
    }

    private 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);
        }
    }

    private static void addSelfToClassloader() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, URISyntaxException, MalformedURLException {
        URLClassLoader ucl = (URLClassLoader) Launch.class.getClassLoader();
        Method addUrl = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
        addUrl.setAccessible(true);
        addUrl.invoke(ucl, Utils.getLibraryPathAsFile(CleanupTweaker.class).toURI().toURL());
    }
}