|
| 1 | +/* |
| 2 | + * A Gradle plugin for the creation of Minecraft mods and MinecraftForge plugins. |
| 3 | + * Copyright (C) 2013-2019 Minecraft Forge |
| 4 | + * |
| 5 | + * This library is free software; you can redistribute it and/or |
| 6 | + * modify it under the terms of the GNU Lesser General Public |
| 7 | + * License as published by the Free Software Foundation; either |
| 8 | + * version 2.1 of the License, or (at your option) any later version. |
| 9 | + * |
| 10 | + * This library is distributed in the hope that it will be useful, |
| 11 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 12 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 13 | + * Lesser General Public License for more details. |
| 14 | + * |
| 15 | + * You should have received a copy of the GNU Lesser General Public |
| 16 | + * License along with this library; if not, write to the Free Software |
| 17 | + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 |
| 18 | + * USA |
| 19 | + */ |
| 20 | + |
| 21 | +package net.minecraftforge.launcher; |
| 22 | + |
| 23 | +import java.io.File; |
| 24 | +import java.io.FileInputStream; |
| 25 | +import java.io.IOException; |
| 26 | +import java.lang.reflect.InvocationTargetException; |
| 27 | +import java.lang.reflect.Method; |
| 28 | +import java.net.URISyntaxException; |
| 29 | +import java.net.URL; |
| 30 | +import java.net.URLClassLoader; |
| 31 | +import java.util.Arrays; |
| 32 | +import java.util.HashMap; |
| 33 | +import java.util.HashSet; |
| 34 | +import java.util.Map; |
| 35 | +import java.util.Set; |
| 36 | +import java.util.jar.Attributes; |
| 37 | +import java.util.jar.JarFile; |
| 38 | +import java.util.jar.Manifest; |
| 39 | + |
| 40 | +import net.minecraftforge.srgutils.MinecraftVersion; |
| 41 | + |
| 42 | +import org.jetbrains.annotations.Nullable; |
| 43 | + |
| 44 | +class FG2Hacks { |
| 45 | + /* ----------- COREMOD AND AT HACK --------- */ |
| 46 | + // coremod hack |
| 47 | + private static final String COREMOD_VAR = "fml.coreMods.load"; |
| 48 | + private static final String COREMOD_MF = "FMLCorePlugin"; |
| 49 | + // AT hack |
| 50 | + private static final String MOD_ATD_CLASS = "net.minecraftforge.fml.common.asm.transformers.ModAccessTransformer"; |
| 51 | + private static final String MOD_AT_METHOD = "addJar"; |
| 52 | + |
| 53 | + private static final MinecraftVersion FG2_START = MinecraftVersion.from("1.8"); |
| 54 | + private static final MinecraftVersion FG2_END = MinecraftVersion.from("1.12.2"); |
| 55 | + private static @Nullable MinecraftVersion mcVer(String ver) { |
| 56 | + try { |
| 57 | + return MinecraftVersion.from(ver); |
| 58 | + } catch (IllegalArgumentException e) { |
| 59 | + return null; |
| 60 | + } |
| 61 | + } |
| 62 | + |
| 63 | + static void searchCoremods(String mcVersion) { |
| 64 | + MinecraftVersion currentMC = mcVer(mcVersion); |
| 65 | + // Check if we're on a known version, between 1.8 and 1.12.2 |
| 66 | + if (currentMC == null || currentMC.compareTo(FG2_START) < 0 || currentMC.compareTo(FG2_END) > 0) |
| 67 | + return; |
| 68 | + |
| 69 | + // initialize AT hack Method |
| 70 | + AtRegistrar atRegistrar = new AtRegistrar(); |
| 71 | + |
| 72 | + Map<String, File> coreMap = new HashMap<>(); |
| 73 | + // We're on a legacy Minecraft Version, which means we should be running Java 8, which means the system classloader should be URLClassLoader |
| 74 | + URLClassLoader urlClassLoader = (URLClassLoader)FG2Hacks.class.getClassLoader(); |
| 75 | + // Fine any coremods from the classpath |
| 76 | + for (URL url : urlClassLoader.getURLs()) { |
| 77 | + try { |
| 78 | + searchCoremodAtUrl(url, atRegistrar, coreMap); |
| 79 | + } catch (IOException | InvocationTargetException | IllegalAccessException | URISyntaxException e) { |
| 80 | + Main.LOGGER.warn("FG2Hacks failed to search for coremod at url " + url, e); |
| 81 | + } |
| 82 | + } |
| 83 | + |
| 84 | + // Set The env to anything we've found from the classpath |
| 85 | + Set<String> coremodsSet = new HashSet<>(); |
| 86 | + String coremodEnv = System.getProperty(COREMOD_VAR); |
| 87 | + if (coremodEnv != null && !coremodEnv.isEmpty()) |
| 88 | + coremodsSet.addAll(Arrays.asList(coremodEnv.split(","))); |
| 89 | + coremodsSet.addAll(coreMap.keySet()); |
| 90 | + System.setProperty(COREMOD_VAR, String.join(",", coremodsSet)); |
| 91 | + |
| 92 | + /* |
| 93 | + // ok.. tweaker hack now. |
| 94 | + if (!Strings.isNullOrEmpty(common.getTweakClass())) { |
| 95 | + common.extras.add("--tweakClass"); |
| 96 | + common.extras.add("net.minecraftforge.gradle.tweakers.CoremodTweaker"); |
| 97 | + } |
| 98 | + */ |
| 99 | + } |
| 100 | + |
| 101 | + private static void searchCoremodAtUrl(URL url, AtRegistrar atRegistrar, Map<String, File> coreMods) throws IOException, InvocationTargetException, IllegalAccessException, URISyntaxException { |
| 102 | + if (!url.getProtocol().startsWith("file")) // because file urls start with file:// |
| 103 | + return; |
| 104 | + |
| 105 | + File coreMod = new File(url.toURI().getPath()); |
| 106 | + if (!coreMod.exists()) |
| 107 | + return; |
| 108 | + |
| 109 | + Manifest manifest = null; |
| 110 | + if (coreMod.isDirectory()) { |
| 111 | + File manifestMF = new File(coreMod, "META-INF/MANIFEST.MF"); |
| 112 | + if (manifestMF.exists()) { |
| 113 | + FileInputStream stream = new FileInputStream(manifestMF); |
| 114 | + manifest = new Manifest(stream); |
| 115 | + stream.close(); |
| 116 | + } |
| 117 | + } else if (coreMod.getName().endsWith("jar")) { |
| 118 | + try (JarFile jar = new JarFile(coreMod)) { |
| 119 | + manifest = jar.getManifest(); |
| 120 | + if (manifest != null) |
| 121 | + atRegistrar.addJar(jar, manifest); |
| 122 | + } |
| 123 | + } |
| 124 | + |
| 125 | + // we got the manifest? use it. |
| 126 | + if (manifest != null) { |
| 127 | + String clazz = manifest.getMainAttributes().getValue(COREMOD_MF); |
| 128 | + if (clazz != null && !clazz.isEmpty()) { |
| 129 | + Main.LOGGER.info("Found and added coremod: " + clazz); |
| 130 | + coreMods.put(clazz, coreMod); |
| 131 | + } |
| 132 | + } |
| 133 | + } |
| 134 | + |
| 135 | + /** |
| 136 | + * Hack to register jar ATs with Minecraft Forge |
| 137 | + */ |
| 138 | + private static final class AtRegistrar { |
| 139 | + private static final Attributes.Name FMLAT = new Attributes.Name("FMLAT"); |
| 140 | + @Nullable |
| 141 | + private Method newMethod = null; |
| 142 | + @Nullable |
| 143 | + private Method oldMethod = null; |
| 144 | + |
| 145 | + private AtRegistrar() { |
| 146 | + try { |
| 147 | + Class<?> modAtdClass = Class.forName(MOD_ATD_CLASS); |
| 148 | + try { |
| 149 | + newMethod = modAtdClass.getDeclaredMethod(MOD_AT_METHOD, JarFile.class, String.class); |
| 150 | + } catch (NoSuchMethodException | SecurityException ignored) { |
| 151 | + try { |
| 152 | + oldMethod = modAtdClass.getDeclaredMethod(MOD_AT_METHOD, JarFile.class); |
| 153 | + } catch (NoSuchMethodException | SecurityException ignored2) { |
| 154 | + Main.LOGGER.error("Failed to find method " + MOD_ATD_CLASS + '.' + MOD_AT_METHOD); |
| 155 | + } |
| 156 | + } |
| 157 | + } catch (ClassNotFoundException e) { |
| 158 | + Main.LOGGER.error("Failed to find class " + MOD_ATD_CLASS); |
| 159 | + } |
| 160 | + } |
| 161 | + |
| 162 | + public void addJar(JarFile jarFile, Manifest manifest) throws InvocationTargetException, IllegalAccessException { |
| 163 | + if (newMethod != null) { |
| 164 | + String ats = manifest.getMainAttributes().getValue(FMLAT); |
| 165 | + if (ats != null && !ats.isEmpty()) |
| 166 | + newMethod.invoke(null, jarFile, ats); |
| 167 | + } else if (oldMethod != null) { |
| 168 | + oldMethod.invoke(null, jarFile); |
| 169 | + } |
| 170 | + } |
| 171 | + } |
| 172 | +} |
0 commit comments