diff --git a/fml/build.xml b/fml/build.xml index 7ba91c6b5a..a7858e5cde 100644 --- a/fml/build.xml +++ b/fml/build.xml @@ -15,8 +15,8 @@ - - + + @@ -34,11 +34,11 @@ - + + + + - - - @@ -54,7 +54,7 @@ - + @@ -89,19 +89,19 @@ - - - - - - - - + + + + + + + + - - - + + + @@ -110,11 +110,11 @@ - - - - - + + + + + @@ -140,19 +140,19 @@ - - + + - + - - - - + + + + - - - + + + @@ -205,25 +205,25 @@ - + - - + + - + - + - - + + - + @@ -242,25 +242,25 @@ You have decided not to continue. This script will stop now. Preparing the MCP environment at ${mcp.home} - + Moving old patched sources at ${patch.mcp.srcdir} out of the way - + Deleting old patch references at ${clean.mcp.srcdir} - + Creating new patch references at ${clean.mcp.srcdir} - + - - + + Creating clean patched references at ${patch.mcp.srcdir} - + - - + + Setup complete! You should now be able to open ${basedir}/eclipse as a workspace in eclipse and import/refresh the FML project @@ -284,45 +284,45 @@ Moving old patched sources at ${mcp.home}/src-work out of the way - + - + - + - + - + - + - + - + - + - + - - + + - + - + A patch is out of date. Update your patches! @@ -332,8 +332,8 @@ - - + + @@ -341,30 +341,43 @@ Extracting fresh eclipse workspace to ${basedir}/eclipse - + - + - + - + - - ${env.JENKINS_HOME} ${universal.jarname} ${sign.KEYPASS} - + + ${env.JENKINS_HOME} ${universal.jarname} ${sign.KEYPASS} + + + + + + + + + + + + + + diff --git a/fml/common/cpw/mods/fml/common/ModClassLoader.java b/fml/common/cpw/mods/fml/common/ModClassLoader.java index 78ae96ebf2..c517d5d33c 100644 --- a/fml/common/cpw/mods/fml/common/ModClassLoader.java +++ b/fml/common/cpw/mods/fml/common/ModClassLoader.java @@ -5,7 +5,7 @@ * are made available under the terms of the GNU Lesser Public License v2.1 * which accompanies this distribution, and is available at * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html - * + * * Contributors: * cpw - implementation */ @@ -20,12 +20,13 @@ import java.net.URLClassLoader; import java.util.List; import java.util.logging.Level; +import net.minecraft.launchwrapper.LaunchClassLoader; + import com.google.common.collect.ImmutableList; import cpw.mods.fml.common.asm.ASMTransformer; import cpw.mods.fml.common.asm.transformers.AccessTransformer; import cpw.mods.fml.common.modloader.BaseModProxy; -import cpw.mods.fml.relauncher.RelaunchClassLoader; /** * A simple delegating class loader used to load mods into the system @@ -37,11 +38,11 @@ import cpw.mods.fml.relauncher.RelaunchClassLoader; public class ModClassLoader extends URLClassLoader { private static final List STANDARD_LIBRARIES = ImmutableList.of("jinput.jar", "lwjgl.jar", "lwjgl_util.jar"); - private RelaunchClassLoader mainClassLoader; + private LaunchClassLoader mainClassLoader; public ModClassLoader(ClassLoader parent) { super(new URL[0], null); - this.mainClassLoader = (RelaunchClassLoader)parent; + this.mainClassLoader = (LaunchClassLoader)parent; } public void addFile(File modFile) throws MalformedURLException diff --git a/fml/common/cpw/mods/fml/common/asm/FMLSanityChecker.java b/fml/common/cpw/mods/fml/common/asm/FMLSanityChecker.java index d770913f9f..9b2527459d 100644 --- a/fml/common/cpw/mods/fml/common/asm/FMLSanityChecker.java +++ b/fml/common/cpw/mods/fml/common/asm/FMLSanityChecker.java @@ -35,6 +35,8 @@ import java.util.Map; import javax.swing.JOptionPane; +import net.minecraft.launchwrapper.LaunchClassLoader; + import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.FieldVisitor; @@ -43,10 +45,9 @@ import org.objectweb.asm.Opcodes; import cpw.mods.fml.common.CertificateHelper; import cpw.mods.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper; import cpw.mods.fml.common.patcher.ClassPatchManager; +import cpw.mods.fml.relauncher.FMLLaunchHandler; import cpw.mods.fml.relauncher.FMLRelaunchLog; -import cpw.mods.fml.relauncher.FMLRelauncher; import cpw.mods.fml.relauncher.IFMLCallHook; -import cpw.mods.fml.relauncher.RelaunchClassLoader; public class FMLSanityChecker implements IFMLCallHook { @@ -71,7 +72,7 @@ public class FMLSanityChecker implements IFMLCallHook } } - private RelaunchClassLoader cl; + private LaunchClassLoader cl; @Override public Void call() throws Exception @@ -140,12 +141,11 @@ public class FMLSanityChecker implements IFMLCallHook @Override public void injectData(Map data) { - cl = (RelaunchClassLoader) data.get("classLoader"); + cl = (LaunchClassLoader) data.get("classLoader"); File mcDir = (File)data.get("mcLocation"); FMLDeobfuscatingRemapper.INSTANCE.setup(mcDir, cl, (String) data.get("deobfuscationFileName")); File binpatches = new File(mcDir,"binpatch"); - File side = new File(binpatches,FMLRelauncher.side().toLowerCase(Locale.ENGLISH)); - ClassPatchManager.INSTANCE.setup(side); + ClassPatchManager.INSTANCE.setup(FMLLaunchHandler.side(), getClass().getProtectionDomain().getCodeSource()); } } diff --git a/fml/common/cpw/mods/fml/common/asm/transformers/SideTransformer.java b/fml/common/cpw/mods/fml/common/asm/transformers/SideTransformer.java index 3c9505411e..feecf88daf 100644 --- a/fml/common/cpw/mods/fml/common/asm/transformers/SideTransformer.java +++ b/fml/common/cpw/mods/fml/common/asm/transformers/SideTransformer.java @@ -5,7 +5,7 @@ * are made available under the terms of the GNU Lesser Public License v2.1 * which accompanies this distribution, and is available at * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html - * + * * Contributors: * cpw - implementation */ @@ -23,13 +23,13 @@ import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.tree.FieldNode; import org.objectweb.asm.tree.MethodNode; -import cpw.mods.fml.relauncher.FMLRelauncher; +import cpw.mods.fml.relauncher.FMLLaunchHandler; import cpw.mods.fml.relauncher.IClassTransformer; import cpw.mods.fml.relauncher.SideOnly; public class SideTransformer implements IClassTransformer { - private static String SIDE = FMLRelauncher.side(); + private static String SIDE = FMLLaunchHandler.side().name(); private static final boolean DEBUG = false; @SuppressWarnings("unchecked") @Override diff --git a/fml/common/cpw/mods/fml/common/asm/transformers/deobf/FMLDeobfuscatingRemapper.java b/fml/common/cpw/mods/fml/common/asm/transformers/deobf/FMLDeobfuscatingRemapper.java index 28f2142bb1..30ce85cf3d 100644 --- a/fml/common/cpw/mods/fml/common/asm/transformers/deobf/FMLDeobfuscatingRemapper.java +++ b/fml/common/cpw/mods/fml/common/asm/transformers/deobf/FMLDeobfuscatingRemapper.java @@ -26,6 +26,8 @@ import java.util.logging.Level; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; +import net.minecraft.launchwrapper.LaunchClassLoader; + import org.objectweb.asm.ClassReader; import org.objectweb.asm.commons.Remapper; @@ -49,7 +51,6 @@ import com.google.common.io.InputSupplier; import cpw.mods.fml.common.FMLLog; import cpw.mods.fml.relauncher.FMLRelaunchLog; -import cpw.mods.fml.relauncher.RelaunchClassLoader; import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.tree.FieldNode; @@ -65,7 +66,7 @@ public class FMLDeobfuscatingRemapper extends Remapper { private Map> fieldNameMaps; private Map> methodNameMaps; - private RelaunchClassLoader classLoader; + private LaunchClassLoader classLoader; private FMLDeobfuscatingRemapper() { @@ -124,7 +125,7 @@ public class FMLDeobfuscatingRemapper extends Remapper { fieldNameMaps = Maps.newHashMapWithExpectedSize(rawFieldMaps.size()); } - public void setup(File mcDir, RelaunchClassLoader classLoader, String deobfFileName) + public void setup(File mcDir, LaunchClassLoader classLoader, String deobfFileName) { this.classLoader = classLoader; try diff --git a/fml/common/cpw/mods/fml/common/discovery/ModDiscoverer.java b/fml/common/cpw/mods/fml/common/discovery/ModDiscoverer.java index ffe13098b6..1e4ab0ca3e 100644 --- a/fml/common/cpw/mods/fml/common/discovery/ModDiscoverer.java +++ b/fml/common/cpw/mods/fml/common/discovery/ModDiscoverer.java @@ -27,7 +27,7 @@ import cpw.mods.fml.common.FMLLog; import cpw.mods.fml.common.LoaderException; import cpw.mods.fml.common.ModClassLoader; import cpw.mods.fml.common.ModContainer; -import cpw.mods.fml.relauncher.RelaunchLibraryManager; +import cpw.mods.fml.relauncher.CoreModManager; public class ModDiscoverer { @@ -41,7 +41,7 @@ public class ModDiscoverer public void findClasspathMods(ModClassLoader modClassLoader) { - List knownLibraries = ImmutableList.builder().addAll(modClassLoader.getDefaultLibraries()).addAll(RelaunchLibraryManager.getLibraries()).build(); + List knownLibraries = ImmutableList.builder().addAll(modClassLoader.getDefaultLibraries()).addAll(CoreModManager.getLibraries()).build(); File[] minecraftSources = modClassLoader.getParentSources(); if (minecraftSources.length == 1 && minecraftSources[0].isFile()) { diff --git a/fml/common/cpw/mods/fml/common/launcher/FMLServerTweaker.java b/fml/common/cpw/mods/fml/common/launcher/FMLServerTweaker.java new file mode 100644 index 0000000000..2ba98f0a25 --- /dev/null +++ b/fml/common/cpw/mods/fml/common/launcher/FMLServerTweaker.java @@ -0,0 +1,18 @@ +package cpw.mods.fml.common.launcher; + +import cpw.mods.fml.relauncher.FMLLaunchHandler; +import net.minecraft.launchwrapper.LaunchClassLoader; + +public class FMLServerTweaker extends FMLTweaker { + @Override + public String getLaunchTarget() + { + return "net.minecraft.server.MinecraftServer"; + } + + @Override + public void injectIntoClassLoader(LaunchClassLoader classLoader) + { + FMLLaunchHandler.configureForServerLaunch(classLoader, this); + } +} diff --git a/fml/common/cpw/mods/fml/common/launcher/FMLTweaker.java b/fml/common/cpw/mods/fml/common/launcher/FMLTweaker.java new file mode 100644 index 0000000000..a536680c44 --- /dev/null +++ b/fml/common/cpw/mods/fml/common/launcher/FMLTweaker.java @@ -0,0 +1,49 @@ +package cpw.mods.fml.common.launcher; + +import java.io.File; +import java.util.List; + +import cpw.mods.fml.relauncher.FMLLaunchHandler; + +import net.minecraft.launchwrapper.ITweaker; +import net.minecraft.launchwrapper.LaunchClassLoader; + +public class FMLTweaker implements ITweaker { + private List args; + private File gameDir; + private File assetsDir; + private String profile; + + @Override + public void acceptOptions(List args, File gameDir, File assetsDir, String profile) + { + this.args = args; + this.gameDir = gameDir; + this.assetsDir = assetsDir; + this.profile = profile; + } + + @Override + public void injectIntoClassLoader(LaunchClassLoader classLoader) + { + FMLLaunchHandler.configureForClientLaunch(classLoader, this); + } + + @Override + public String getLaunchTarget() + { + return "net.minecraft.client.Minecraft"; + } + + @Override + public String[] getLaunchArguments() + { + return args.toArray(new String[args.size()]); + } + + public File getGameDir() + { + return gameDir; + } + +} diff --git a/fml/common/cpw/mods/fml/common/patcher/ClassPatchManager.java b/fml/common/cpw/mods/fml/common/patcher/ClassPatchManager.java index 56c0b05b72..b8f15bcbf5 100644 --- a/fml/common/cpw/mods/fml/common/patcher/ClassPatchManager.java +++ b/fml/common/cpw/mods/fml/common/patcher/ClassPatchManager.java @@ -3,9 +3,19 @@ package cpw.mods.fml.common.patcher; import java.io.File; import java.io.FilenameFilter; import java.io.IOException; +import java.net.URISyntaxException; +import java.security.CodeSource; +import java.util.Collections; import java.util.List; +import java.util.Locale; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; import java.util.logging.Level; +import java.util.regex.Pattern; +import com.google.common.base.Joiner; +import com.google.common.base.Strings; +import com.google.common.base.Throwables; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ListMultimap; import com.google.common.io.ByteArrayDataInput; @@ -13,6 +23,8 @@ import com.google.common.io.ByteStreams; import com.google.common.io.Files; import cpw.mods.fml.common.FMLLog; +import cpw.mods.fml.relauncher.FMLRelaunchLog; +import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.repackage.com.nothome.delta.GDiffPatcher; public class ClassPatchManager { @@ -67,48 +79,59 @@ public class ClassPatchManager { return inputData; } - public void setup(File dirToScan) + public void setup(Side side, CodeSource fmlLib) { - File[] patchFiles = dirToScan.listFiles(new FilenameFilter() + Pattern binpatchMatcher = Pattern.compile(String.format("binpatch/%s/*.binpatch", side.toString().toLowerCase(Locale.ENGLISH))); + JarFile fmlJar; + try { - @Override - public boolean accept(File dir, String name) - { - return Files.getFileExtension(new File(dir,name).getPath()).equals("binpatch"); - } - }); - - if (patchFiles == null) - { - return; + File fmlJarFile = new File(fmlLib.getLocation().toURI()); + fmlJar = new JarFile(fmlJarFile); } + catch (Exception e) + { + FMLRelaunchLog.log(Level.SEVERE, e, "Error occurred reading binary patches. Problems may occur"); + throw Throwables.propagate(e); + } + patches = ArrayListMultimap.create(); - for (File patch : patchFiles) + + for (JarEntry entry : Collections.list(fmlJar.entries())) { - FMLLog.finest("Reading patch data from %s", patch.getAbsolutePath()); - ByteArrayDataInput input; - try + if (binpatchMatcher.matcher(entry.getName()).matches()) { - input = ByteStreams.newDataInput(Files.toByteArray(patch)); + ClassPatch cp = readPatch(entry, fmlJar); + if (cp != null) + { + patches.put(cp.sourceClassName, cp); + } } - catch (IOException e) - { - FMLLog.log(Level.WARNING, e, "Unable to read binpatch file %s - ignoring", patch.getAbsolutePath()); - continue; - } - String name = input.readUTF(); - String sourceClassName = input.readUTF(); - String targetClassName = input.readUTF(); - boolean exists = input.readBoolean(); - int patchLength = input.readInt(); - byte[] patchBytes = new byte[patchLength]; - input.readFully(patchBytes); - - ClassPatch cp = new ClassPatch(name, sourceClassName, targetClassName, exists, patchBytes); - patches.put(sourceClassName, cp); } + FMLLog.fine("Read %d binary patches from %s", patches.size(), fmlJar.getName()); + FMLLog.fine("Patch list :\n\t%s", Joiner.on("\t\n").join(patches.asMap().entrySet())); + } - FMLLog.fine("Read %d binary patches from %s", patches.size(), dirToScan.getAbsolutePath()); - FMLLog.fine("Patch list : %s", patches); + private ClassPatch readPatch(JarEntry patchEntry, JarFile jarFile) + { + FMLLog.finest("Reading patch data from %s in file %s", patchEntry.getName(), jarFile.getName()); + ByteArrayDataInput input; + try + { + input = ByteStreams.newDataInput(ByteStreams.toByteArray(jarFile.getInputStream(patchEntry))); + } + catch (IOException e) + { + FMLLog.log(Level.WARNING, e, "Unable to read binpatch file %s - ignoring", patchEntry.getName()); + return null; + } + String name = input.readUTF(); + String sourceClassName = input.readUTF(); + String targetClassName = input.readUTF(); + boolean exists = input.readBoolean(); + int patchLength = input.readInt(); + byte[] patchBytes = new byte[patchLength]; + input.readFully(patchBytes); + + return new ClassPatch(name, sourceClassName, targetClassName, exists, patchBytes); } } diff --git a/fml/common/cpw/mods/fml/relauncher/ArgsWrapper.java b/fml/common/cpw/mods/fml/relauncher/ArgsWrapper.java deleted file mode 100644 index 5f4d1f6dfc..0000000000 --- a/fml/common/cpw/mods/fml/relauncher/ArgsWrapper.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Forge Mod Loader - * Copyright (c) 2012-2013 cpw. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser Public License v2.1 - * which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html - * - * Contributors: - * cpw - implementation - */ - -package cpw.mods.fml.relauncher; - -public class ArgsWrapper -{ - public ArgsWrapper(String[] args) - { - this.args=args; - } - - public String[] args; -} diff --git a/fml/common/cpw/mods/fml/relauncher/RelaunchLibraryManager.java b/fml/common/cpw/mods/fml/relauncher/CoreModManager.java similarity index 94% rename from fml/common/cpw/mods/fml/relauncher/RelaunchLibraryManager.java rename to fml/common/cpw/mods/fml/relauncher/CoreModManager.java index af870fa8f5..87ec97b798 100644 --- a/fml/common/cpw/mods/fml/relauncher/RelaunchLibraryManager.java +++ b/fml/common/cpw/mods/fml/relauncher/CoreModManager.java @@ -37,11 +37,13 @@ import java.util.jar.Attributes; import java.util.jar.JarFile; import java.util.logging.Level; +import net.minecraft.launchwrapper.LaunchClassLoader; + import cpw.mods.fml.common.CertificateHelper; import cpw.mods.fml.relauncher.IFMLLoadingPlugin.MCVersion; import cpw.mods.fml.relauncher.IFMLLoadingPlugin.TransformerExclusions; -public class RelaunchLibraryManager +public class CoreModManager { private static String[] rootPlugins = { "cpw.mods.fml.relauncher.FMLCorePlugin" , "net.minecraftforge.classloading.FMLForgePlugin" }; private static List loadedLibraries = new ArrayList(); @@ -50,12 +52,12 @@ public class RelaunchLibraryManager private static List libraries; private static boolean deobfuscatedEnvironment; - public static void handleLaunch(File mcDir, RelaunchClassLoader actualClassLoader) + public static void handleLaunch(File mcDir, LaunchClassLoader classLoader) { try { // Are we in a 'decompiled' environment? - byte[] bs = actualClassLoader.getClassBytes("net.minecraft.world.World"); + byte[] bs = classLoader.getClassBytes("net.minecraft.world.World"); if (bs != null) { FMLRelaunchLog.info("Managed to load a deobfuscated Minecraft name- we are in a deobfuscated environment. Skipping runtime deobfuscation"); @@ -72,17 +74,12 @@ public class RelaunchLibraryManager } pluginLocations = new HashMap(); loadPlugins = new ArrayList(); - libraries = new ArrayList(); for (String s : rootPlugins) { try { - IFMLLoadingPlugin plugin = (IFMLLoadingPlugin) Class.forName(s, true, actualClassLoader).newInstance(); + IFMLLoadingPlugin plugin = (IFMLLoadingPlugin) Class.forName(s, true, classLoader).newInstance(); loadPlugins.add(plugin); - for (String libName : plugin.getLibraryRequestClass()) - { - libraries.add((ILibrarySet) Class.forName(libName, true, actualClassLoader).newInstance()); - } } catch (Exception e) { @@ -107,14 +104,14 @@ public class RelaunchLibraryManager FMLRelaunchLog.info("Found a command line coremod : %s", s); try { - actualClassLoader.addTransformerExclusion(s); - Class coreModClass = Class.forName(s, true, actualClassLoader); + classLoader.addTransformerExclusion(s); + Class coreModClass = Class.forName(s, true, classLoader); TransformerExclusions trExclusions = coreModClass.getAnnotation(IFMLLoadingPlugin.TransformerExclusions.class); if (trExclusions!=null) { for (String st : trExclusions.value()) { - actualClassLoader.addTransformerExclusion(st); + classLoader.addTransformerExclusion(st); } } IFMLLoadingPlugin plugin = (IFMLLoadingPlugin) coreModClass.newInstance(); @@ -123,7 +120,7 @@ public class RelaunchLibraryManager { for (String libName : plugin.getLibraryRequestClass()) { - libraries.add((ILibrarySet) Class.forName(libName, true, actualClassLoader).newInstance()); + libraries.add((ILibrarySet) Class.forName(libName, true, classLoader).newInstance()); } } } @@ -133,7 +130,7 @@ public class RelaunchLibraryManager throw new RuntimeException(e); } } - discoverCoreMods(mcDir, actualClassLoader, loadPlugins, libraries); + discoverCoreMods(mcDir, classLoader, loadPlugins, libraries); List caughtErrors = new ArrayList(); try @@ -213,7 +210,7 @@ public class RelaunchLibraryManager try { - actualClassLoader.addURL(libFile.toURI().toURL()); + classLoader.addURL(libFile.toURI().toURL()); loadedLibraries.add(libName); } catch (MalformedURLException e) @@ -268,14 +265,14 @@ public class RelaunchLibraryManager { for (String xformClass : plug.getASMTransformerClass()) { - actualClassLoader.registerTransformer(xformClass); + classLoader.registerTransformer(xformClass); } } } // Deobfuscation transformer, always last if (!deobfuscatedEnvironment) { - actualClassLoader.registerTransformer("cpw.mods.fml.common.asm.transformers.DeobfuscationTransformer"); + classLoader.registerTransformer("cpw.mods.fml.common.asm.transformers.DeobfuscationTransformer"); } downloadMonitor.updateProgressString("Running coremod plugins"); Map data = new HashMap(); @@ -292,10 +289,10 @@ public class RelaunchLibraryManager { try { - IFMLCallHook call = (IFMLCallHook) Class.forName(setupClass, true, actualClassLoader).newInstance(); + IFMLCallHook call = (IFMLCallHook) Class.forName(setupClass, true, classLoader).newInstance(); Map callData = new HashMap(); callData.put("mcLocation", mcDir); - callData.put("classLoader", actualClassLoader); + callData.put("classLoader", classLoader); callData.put("coremodLocation", pluginLocations.get(plugin)); callData.put("deobfuscationFileName", FMLInjectionData.debfuscationDataName()); call.injectData(callData); @@ -317,7 +314,7 @@ public class RelaunchLibraryManager try { downloadMonitor.updateProgressString("Validating minecraft"); - Class loaderClazz = Class.forName("cpw.mods.fml.common.Loader", true, actualClassLoader); + Class loaderClazz = Class.forName("cpw.mods.fml.common.Loader", true, classLoader); Method m = loaderClazz.getMethod("injectData", Object[].class); m.invoke(null, (Object)FMLInjectionData.data()); m = loaderClazz.getMethod("instance"); @@ -333,7 +330,7 @@ public class RelaunchLibraryManager } } - private static void discoverCoreMods(File mcDir, RelaunchClassLoader classLoader, List loadPlugins, List libraries) + private static void discoverCoreMods(File mcDir, LaunchClassLoader classLoader, List loadPlugins, List libraries) { downloadMonitor.updateProgressString("Discovering coremods"); File coreMods = setupCoreModDir(mcDir); diff --git a/fml/common/cpw/mods/fml/relauncher/FMLInjectionData.java b/fml/common/cpw/mods/fml/relauncher/FMLInjectionData.java index cd9dd49a10..582d9e4960 100644 --- a/fml/common/cpw/mods/fml/relauncher/FMLInjectionData.java +++ b/fml/common/cpw/mods/fml/relauncher/FMLInjectionData.java @@ -5,7 +5,7 @@ * are made available under the terms of the GNU Lesser Public License v2.1 * which accompanies this distribution, and is available at * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html - * + * * Contributors: * cpw - implementation */ @@ -20,6 +20,8 @@ import java.util.List; import java.util.Properties; import java.util.logging.Level; +import net.minecraft.launchwrapper.LaunchClassLoader; + public class FMLInjectionData { static File minecraftHome; @@ -33,7 +35,7 @@ public class FMLInjectionData public static List containers = new ArrayList(); - static void build(File mcHome, RelaunchClassLoader classLoader) + static void build(File mcHome, LaunchClassLoader classLoader) { minecraftHome = mcHome; InputStream stream = classLoader.getResourceAsStream("fmlversion.properties"); diff --git a/fml/common/cpw/mods/fml/relauncher/FMLLaunchHandler.java b/fml/common/cpw/mods/fml/relauncher/FMLLaunchHandler.java new file mode 100644 index 0000000000..fb2f9a482a --- /dev/null +++ b/fml/common/cpw/mods/fml/relauncher/FMLLaunchHandler.java @@ -0,0 +1,116 @@ +/* + * Forge Mod Loader + * Copyright (c) 2012-2013 cpw. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Lesser Public License v2.1 + * which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * + * Contributors: + * cpw - implementation + */ + +package cpw.mods.fml.relauncher; + +import java.applet.Applet; +import java.io.File; +import java.lang.reflect.Method; +import java.net.URLClassLoader; + +import javax.swing.JDialog; +import javax.swing.JOptionPane; + +import com.google.common.base.Throwables; + +import cpw.mods.fml.common.launcher.FMLTweaker; + +import net.minecraft.launchwrapper.LaunchClassLoader; + +public class FMLLaunchHandler +{ + private static FMLLaunchHandler INSTANCE; + static Side side; + private LaunchClassLoader classLoader; + private FMLTweaker tweaker; + private File minecraftHome; + + public static void configureForClientLaunch(LaunchClassLoader loader, FMLTweaker tweaker) + { + instance(loader, tweaker).setupClient(); + } + + public static void configureForServerLaunch(LaunchClassLoader loader, FMLTweaker tweaker) + { + instance(loader, tweaker).setupServer(); + } + + private static FMLLaunchHandler instance(LaunchClassLoader launchLoader, FMLTweaker tweaker) + { + if (INSTANCE == null) + { + INSTANCE = new FMLLaunchHandler(launchLoader, tweaker); + } + return INSTANCE; + + } + + private FMLLaunchHandler(LaunchClassLoader launchLoader, FMLTweaker tweaker) + { + this.classLoader = launchLoader; + this.tweaker = tweaker; + this.minecraftHome = tweaker.getGameDir(); + this.classLoader.addClassLoaderExclusion("cpw.mods.fml.relauncher."); + this.classLoader.addClassLoaderExclusion("net.minecraftforge.classloading."); + this.classLoader.addTransformerExclusion("cpw.mods.fml.common.asm.transformers.deobf."); + this.classLoader.addTransformerExclusion("cpw.mods.fml.common.patcher."); + } + + private void showWindow(boolean showIt) + { + if (CoreModManager.downloadMonitor != null) { return; } + CoreModManager.downloadMonitor = new DummyDownloader(); + } + + private void setupClient() + { + showWindow(true); + FMLRelaunchLog.logFileNamePattern = "ForgeModLoader-client-%g.log"; + side = Side.CLIENT; + setupHome(); + } + + private void setupServer() + { + showWindow(false); + FMLRelaunchLog.logFileNamePattern = "ForgeModLoader-server-%g.log"; + side = Side.SERVER; + setupHome(); + + } + + private void setupHome() + { + FMLInjectionData.build(minecraftHome, classLoader); + FMLRelaunchLog.minecraftHome = minecraftHome; + FMLRelaunchLog.info("Forge Mod Loader version %s.%s.%s.%s for Minecraft %s loading", FMLInjectionData.major, FMLInjectionData.minor, + FMLInjectionData.rev, FMLInjectionData.build, FMLInjectionData.mccversion, FMLInjectionData.mcpversion); + FMLRelaunchLog.info("Java is %s, version %s, running on %s:%s:%s, installed at %s", System.getProperty("java.vm.name"), System.getProperty("java.version"), System.getProperty("os.name"), System.getProperty("os.arch"), System.getProperty("os.version"), System.getProperty("java.home")); + FMLRelaunchLog.fine("Java classpath at launch is %s", System.getProperty("java.class.path")); + FMLRelaunchLog.fine("Java library path at launch is %s", System.getProperty("java.library.path")); + + try + { + CoreModManager.handleLaunch(minecraftHome, classLoader); + } + catch (Throwable t) + { + FMLRelaunchLog.severe("An error occurred trying to configure the minecraft home at %s for Forge Mod Loader", minecraftHome.getAbsolutePath()); + throw Throwables.propagate(t); + } + } + + public static Side side() + { + return side; + } +} diff --git a/fml/common/cpw/mods/fml/relauncher/FMLRelaunchLog.java b/fml/common/cpw/mods/fml/relauncher/FMLRelaunchLog.java index 1b4daec938..7b7515b394 100644 --- a/fml/common/cpw/mods/fml/relauncher/FMLRelaunchLog.java +++ b/fml/common/cpw/mods/fml/relauncher/FMLRelaunchLog.java @@ -148,6 +148,8 @@ public class FMLRelaunchLog private static FMLLogFormatter formatter; + static String logFileNamePattern; + private FMLRelaunchLog() { } @@ -174,7 +176,7 @@ public class FMLRelaunchLog formatter = new FMLLogFormatter(); try { - File logPath = new File(minecraftHome, FMLRelauncher.logFileNamePattern); + File logPath = new File(minecraftHome, logFileNamePattern); fileHandler = new FileHandler(logPath.getPath(), 0, 3) { public synchronized void close() throws SecurityException { diff --git a/fml/common/cpw/mods/fml/relauncher/FMLRelauncher.java b/fml/common/cpw/mods/fml/relauncher/FMLRelauncher.java deleted file mode 100644 index 9847462d63..0000000000 --- a/fml/common/cpw/mods/fml/relauncher/FMLRelauncher.java +++ /dev/null @@ -1,335 +0,0 @@ -/* - * Forge Mod Loader - * Copyright (c) 2012-2013 cpw. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser Public License v2.1 - * which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html - * - * Contributors: - * cpw - implementation - */ - -package cpw.mods.fml.relauncher; - -import java.applet.Applet; -import java.io.File; -import java.lang.reflect.Method; -import java.net.URLClassLoader; - -import javax.swing.JDialog; -import javax.swing.JOptionPane; - -public class FMLRelauncher -{ - private static FMLRelauncher INSTANCE; - public static String logFileNamePattern; - static String side; - private RelaunchClassLoader classLoader; - private Object newApplet; - private Class appletClass; - - JDialog popupWindow; - - public static void handleClientRelaunch(ArgsWrapper wrap) - { - logFileNamePattern = "ForgeModLoader-client-%g.log"; - side = "CLIENT"; - instance().relaunchClient(wrap); - } - - public static void handleServerRelaunch(ArgsWrapper wrap) - { - logFileNamePattern = "ForgeModLoader-server-%g.log"; - side = "SERVER"; - instance().relaunchServer(wrap); - } - - static FMLRelauncher instance() - { - if (INSTANCE == null) - { - INSTANCE = new FMLRelauncher(); - } - return INSTANCE; - - } - - private FMLRelauncher() - { - URLClassLoader ucl = (URLClassLoader) getClass().getClassLoader(); - - classLoader = new RelaunchClassLoader(ucl.getURLs()); - - } - - private void showWindow(boolean showIt) - { - if (RelaunchLibraryManager.downloadMonitor != null) { return; } - try - { - if (showIt) - { - RelaunchLibraryManager.downloadMonitor = new Downloader(); - popupWindow = (JDialog) RelaunchLibraryManager.downloadMonitor.makeDialog(); - } - else - { - RelaunchLibraryManager.downloadMonitor = new DummyDownloader(); - } - } - catch (Throwable e) - { - if (RelaunchLibraryManager.downloadMonitor == null) - { - RelaunchLibraryManager.downloadMonitor = new DummyDownloader(); - e.printStackTrace(); - } - else - { - RelaunchLibraryManager.downloadMonitor.makeHeadless(); - } - popupWindow = null; - } - } - - private void relaunchClient(ArgsWrapper wrap) - { - showWindow(true); - // Now we re-inject the home into the "new" minecraft under our control - Class client; - try - { - File minecraftHome = computeExistingClientHome(); - setupHome(minecraftHome); - - client = setupNewClientHome(minecraftHome); - } - finally - { - if (popupWindow != null) - { - popupWindow.setVisible(false); - popupWindow.dispose(); - } - } - - if (RelaunchLibraryManager.downloadMonitor.shouldStopIt()) - { - System.exit(1); - } - try - { - ReflectionHelper.findMethod(client, null, new String[] { "fmlReentry" }, ArgsWrapper.class).invoke(null, wrap); - } - catch (Exception e) - { - e.printStackTrace(); - // Hmmm - } - } - - private Class setupNewClientHome(File minecraftHome) - { - Class client = ReflectionHelper.getClass(classLoader, "net.minecraft.client.Minecraft"); - ReflectionHelper.setPrivateValue(client, null, minecraftHome, - "field_" + "71463_am" /*Separate that so that MCP's updatenames does not replace it*/, - "an", "minecraftDir"); - return client; - } - - private void relaunchServer(ArgsWrapper wrap) - { - showWindow(false); - // Now we re-inject the home into the "new" minecraft under our control - Class server; - File minecraftHome = new File("."); - setupHome(minecraftHome); - - server = ReflectionHelper.getClass(classLoader, "net.minecraft.server.MinecraftServer"); - try - { - ReflectionHelper.findMethod(server, null, new String[] { "fmlReentry" }, ArgsWrapper.class).invoke(null, wrap); - } - catch (Exception e) - { - e.printStackTrace(); - } - } - - private void setupHome(File minecraftHome) - { - FMLInjectionData.build(minecraftHome, classLoader); - FMLRelaunchLog.minecraftHome = minecraftHome; - FMLRelaunchLog.info("Forge Mod Loader version %s.%s.%s.%s for Minecraft %s loading", FMLInjectionData.major, FMLInjectionData.minor, - FMLInjectionData.rev, FMLInjectionData.build, FMLInjectionData.mccversion, FMLInjectionData.mcpversion); - FMLRelaunchLog.info("Java is %s, version %s, running on %s:%s:%s, installed at %s", System.getProperty("java.vm.name"), System.getProperty("java.version"), System.getProperty("os.name"), System.getProperty("os.arch"), System.getProperty("os.version"), System.getProperty("java.home")); - FMLRelaunchLog.fine("Java classpath at launch is %s", System.getProperty("java.class.path")); - FMLRelaunchLog.fine("Java library path at launch is %s", System.getProperty("java.library.path")); - - try - { - RelaunchLibraryManager.handleLaunch(minecraftHome, classLoader); - } - catch (Throwable t) - { - if (popupWindow != null) - { - try - { - String logFile = new File(minecraftHome, "ForgeModLoader-client-0.log").getCanonicalPath(); - JOptionPane.showMessageDialog(popupWindow, String.format( - "
There was a fatal error starting up minecraft and FML

" - + "Minecraft cannot launch in it's current configuration
" - + "Please consult the file %s for further information", logFile, logFile), - "Fatal FML error", JOptionPane.ERROR_MESSAGE); - } - catch (Exception ex) - { - // ah well, we tried - } - } - throw new RuntimeException(t); - } - } - - /** - * @return the location of the client home - */ - private File computeExistingClientHome() - { - Class mcMaster = ReflectionHelper.getClass(getClass().getClassLoader(), "net.minecraft.client.Minecraft"); - // If we get the system property we inject into the old MC, setup the - // dir, then pull the value - String str = System.getProperty("minecraft.applet.TargetDirectory"); - if (str != null) - { - str = str.replace('/', File.separatorChar); - ReflectionHelper.setPrivateValue(mcMaster, null, new File(str), "minecraftDir", "an", "minecraftDir"); - } - // We force minecraft to setup it's homedir very early on so we can - // inject stuff into it - Method setupHome = ReflectionHelper.findMethod(mcMaster, null, new String[] { "func_71380_b", "getMinecraftDir", "b" }); - try - { - setupHome.invoke(null); - } - catch (Exception e) - { - // Hmmm - } - File minecraftHome = ReflectionHelper.getPrivateValue(mcMaster, null, "field_71463_am", "an", "minecraftDir"); - return minecraftHome; - } - - public static void appletEntry(Applet minecraftApplet) - { - side = "CLIENT"; - logFileNamePattern = "ForgeModLoader-client-%g.log"; - instance().relaunchApplet(minecraftApplet); - } - - private void relaunchApplet(Applet minecraftApplet) - { - showWindow(true); - - if (minecraftApplet.getClass().getClassLoader() == classLoader) - { - if (popupWindow != null) - { - popupWindow.setVisible(false); - popupWindow.dispose(); - } - try - { - newApplet = minecraftApplet; - appletClass = ReflectionHelper.getClass(classLoader, "net.minecraft.client.MinecraftApplet"); - ReflectionHelper.findMethod(appletClass, newApplet, new String[] { "fmlInitReentry" }).invoke(newApplet); - return; - } - catch (Exception e) - { - System.out.println("FMLRelauncher.relaunchApplet"); - e.printStackTrace(); - throw new RuntimeException(e); - } - } - - File mcDir = computeExistingClientHome(); - setupHome(mcDir); - setupNewClientHome(mcDir); - - Class parentAppletClass = ReflectionHelper.getClass(getClass().getClassLoader(), "java.applet.Applet"); - - try - { - appletClass = ReflectionHelper.getClass(classLoader, "net.minecraft.client.MinecraftApplet"); - newApplet = appletClass.newInstance(); - Object appletContainer = ReflectionHelper.getPrivateValue(ReflectionHelper.getClass(getClass().getClassLoader(), "java.awt.Component"), - minecraftApplet, "parent"); - - String launcherClassName = System.getProperty("minecraft.applet.WrapperClass", "net.minecraft.Launcher"); - Class launcherClass = ReflectionHelper.getClass(getClass().getClassLoader(), launcherClassName); - if (launcherClass.isInstance(appletContainer)) - { - ReflectionHelper.findMethod(ReflectionHelper.getClass(getClass().getClassLoader(), "java.awt.Container"), minecraftApplet, - new String[] { "removeAll" }).invoke(appletContainer); - ReflectionHelper.findMethod(launcherClass, appletContainer, new String[] { "replace" }, parentAppletClass).invoke(appletContainer, newApplet); - } - else - { - FMLRelaunchLog.severe("Found unknown applet parent %s, unable to inject!\n", appletContainer.getClass().getName()); - throw new RuntimeException(); - } - } - catch (Exception e) - { - throw new RuntimeException(e); - } - finally - { - if (popupWindow != null) - { - popupWindow.setVisible(false); - popupWindow.dispose(); - } - } - } - - public static void appletStart(Applet applet) - { - instance().startApplet(applet); - } - - private void startApplet(Applet applet) - { - if (applet.getClass().getClassLoader() == classLoader) - { - if (popupWindow != null) - { - popupWindow.setVisible(false); - popupWindow.dispose(); - } - if (RelaunchLibraryManager.downloadMonitor.shouldStopIt()) - { - System.exit(1); - } - try - { - ReflectionHelper.findMethod(appletClass, newApplet, new String[] { "fmlStartReentry" }).invoke(newApplet); - } - catch (Exception e) - { - System.out.println("FMLRelauncher.startApplet"); - e.printStackTrace(); - throw new RuntimeException(e); - } - } - return; - } - - public static String side() - { - return side; - } -} diff --git a/fml/common/cpw/mods/fml/relauncher/IFMLLoadingPlugin.java b/fml/common/cpw/mods/fml/relauncher/IFMLLoadingPlugin.java index 3561ebf51e..e0bbd669f7 100644 --- a/fml/common/cpw/mods/fml/relauncher/IFMLLoadingPlugin.java +++ b/fml/common/cpw/mods/fml/relauncher/IFMLLoadingPlugin.java @@ -32,6 +32,7 @@ public interface IFMLLoadingPlugin * * @return a list of classes that implement the ILibrarySet interface */ + @Deprecated String[] getLibraryRequestClass(); /** * Return a list of classes that implements the IClassTransformer interface diff --git a/fml/common/cpw/mods/fml/relauncher/RelaunchClassLoader.java b/fml/common/cpw/mods/fml/relauncher/RelaunchClassLoader.java deleted file mode 100644 index 4dcd9b778e..0000000000 --- a/fml/common/cpw/mods/fml/relauncher/RelaunchClassLoader.java +++ /dev/null @@ -1,473 +0,0 @@ -/* - * Forge Mod Loader - * Copyright (c) 2012-2013 cpw. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser Public License v2.1 - * which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html - * - * Contributors: - * cpw - implementation - */ - -package cpw.mods.fml.relauncher; - -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.JarURLConnection; -import java.net.URL; -import java.net.URLClassLoader; -import java.net.URLConnection; -import java.security.CodeSigner; -import java.security.CodeSource; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Set; -import java.util.jar.Attributes.Name; -import java.util.jar.Attributes; -import java.util.jar.JarEntry; -import java.util.jar.JarFile; -import java.util.jar.Manifest; -import java.util.logging.Level; - -import cpw.mods.fml.common.FMLLog; - -public class RelaunchClassLoader extends URLClassLoader -{ - private List sources; - private ClassLoader parent; - - private List transformers; - private Map cachedClasses; - private Set invalidClasses; - - private Set classLoaderExceptions = new HashSet(); - private Set transformerExceptions = new HashSet(); - private Map packageManifests = new HashMap(); - private IClassNameTransformer renameTransformer; - - private static Manifest EMPTY = new Manifest(); - - private ThreadLocal loadBuffer = new ThreadLocal(); - - private static final String[] RESERVED = {"CON", "PRN", "AUX", "NUL", "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9", "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9"}; - - private static final boolean DEBUG_CLASSLOADING = Boolean.parseBoolean(System.getProperty("fml.debugClassLoading", "false")); - private static final boolean DEBUG_CLASSLOADING_FINER = DEBUG_CLASSLOADING && Boolean.parseBoolean(System.getProperty("fml.debugClassLoadingFiner", "false")); - private static final boolean DEBUG_CLASSLOADING_SAVE = DEBUG_CLASSLOADING && Boolean.parseBoolean(System.getProperty("fml.debugClassLoadingSave", "false")); - private static File temp_folder = null; - - public RelaunchClassLoader(URL[] sources) - { - super(sources, null); - this.sources = new ArrayList(Arrays.asList(sources)); - this.parent = getClass().getClassLoader(); - this.cachedClasses = new HashMap(1000); - this.invalidClasses = new HashSet(1000); - this.transformers = new ArrayList(2); -// ReflectionHelper.setPrivateValue(ClassLoader.class, null, this, "scl"); - Thread.currentThread().setContextClassLoader(this); - - // standard classloader exclusions - addClassLoaderExclusion("java."); - addClassLoaderExclusion("sun."); - addClassLoaderExclusion("org.lwjgl."); - addClassLoaderExclusion("cpw.mods.fml.relauncher."); - addClassLoaderExclusion("net.minecraftforge.classloading."); - - // standard transformer exclusions - addTransformerExclusion("javax."); - addTransformerExclusion("argo."); - addTransformerExclusion("org.objectweb.asm."); - addTransformerExclusion("com.google.common."); - addTransformerExclusion("org.bouncycastle."); - addTransformerExclusion("cpw.mods.fml.common.asm.transformers.deobf."); - addTransformerExclusion("cpw.mods.fml.common.patcher."); - addTransformerExclusion("cpw.mods.fml.repackage."); - - if (DEBUG_CLASSLOADING_SAVE) - { - int x = 1; - temp_folder = new File(FMLRelaunchLog.minecraftHome, "CLASSLOADER_TEMP"); - while(temp_folder.exists() && x <= 10) - { - temp_folder = new File(FMLRelaunchLog.minecraftHome, "CLASSLOADER_TEMP" + x++); - } - - if (temp_folder.exists()) - { - FMLRelaunchLog.info("DEBUG_CLASSLOADING_SAVE enabled, but 10 temp directories already exist, clean them and try again."); - temp_folder = null; - } - else - { - FMLRelaunchLog.info("DEBUG_CLASSLOADING_SAVE Enabled, saving all classes to \"%s\"", temp_folder.getAbsolutePath().replace('\\', '/')); - temp_folder.mkdirs(); - } - } - } - - public void registerTransformer(String transformerClassName) - { - try - { - IClassTransformer transformer = (IClassTransformer) loadClass(transformerClassName).newInstance(); - transformers.add(transformer); - if (transformer instanceof IClassNameTransformer && renameTransformer == null) - { - renameTransformer = (IClassNameTransformer) transformer; - } - } - catch (Exception e) - { - FMLRelaunchLog.log(Level.SEVERE, e, "A critical problem occured registering the ASM transformer class %s", transformerClassName); - } - } - @Override - public Class findClass(String name) throws ClassNotFoundException - { - if (invalidClasses.contains(name)) - { - throw new ClassNotFoundException(name); - } - for (String st : classLoaderExceptions) - { - if (name.startsWith(st)) - { - return parent.loadClass(name); - } - } - - if (cachedClasses.containsKey(name)) - { - return cachedClasses.get(name); - } - - for (String st : transformerExceptions) - { - if (name.startsWith(st)) - { - try - { - Class cl = super.findClass(name); - cachedClasses.put(name, cl); - return cl; - } - catch (ClassNotFoundException e) - { - invalidClasses.add(name); - throw e; - } - } - } - - try - { - CodeSigner[] signers = null; - String transformedName = transformName(name); - String untransformedName = untransformName(name); - int lastDot = untransformedName.lastIndexOf('.'); - String pkgname = lastDot == -1 ? "" : untransformedName.substring(0, lastDot); - String fName = untransformedName.replace('.', '/').concat(".class"); - String pkgPath = pkgname.replace('.', '/'); - URLConnection urlConnection = findCodeSourceConnectionFor(fName); - if (urlConnection instanceof JarURLConnection && lastDot > -1 && !untransformedName.startsWith("net.minecraft.")) - { - JarURLConnection jarUrlConn = (JarURLConnection)urlConnection; - JarFile jf = jarUrlConn.getJarFile(); - if (jf != null && jf.getManifest() != null) - { - Manifest mf = jf.getManifest(); - JarEntry ent = jf.getJarEntry(fName); - Package pkg = getPackage(pkgname); - getClassBytes(untransformedName); - signers = ent.getCodeSigners(); - if (pkg == null) - { - pkg = definePackage(pkgname, mf, jarUrlConn.getJarFileURL()); - packageManifests.put(pkg, mf); - } - else - { - if (pkg.isSealed() && !pkg.isSealed(jarUrlConn.getJarFileURL())) - { - FMLLog.severe("The jar file %s is trying to seal already secured path %s", jf.getName(), pkgname); - } - else if (isSealed(pkgname, mf)) - { - FMLLog.severe("The jar file %s has a security seal for path %s, but that path is defined and not secure", jf.getName(), pkgname); - } - } - } - } - else if (lastDot > -1 && !untransformedName.startsWith("net.minecraft.")) - { - Package pkg = getPackage(pkgname); - if (pkg == null) - { - pkg = definePackage(pkgname, null, null, null, null, null, null, null); - packageManifests.put(pkg, EMPTY); - } - else if (pkg.isSealed()) - { - FMLLog.severe("The URL %s is defining elements for sealed path %s", urlConnection.getURL(), pkgname); - } - } - byte[] basicClass = getClassBytes(untransformedName); - byte[] transformedClass = runTransformers(untransformedName, transformedName, basicClass); - saveTransformedClass(transformedClass, transformedName); - Class cl = defineClass(transformedName, transformedClass, 0, transformedClass.length, (urlConnection == null ? null : new CodeSource(urlConnection.getURL(), signers))); - cachedClasses.put(transformedName, cl); - return cl; - } - catch (Throwable e) - { - invalidClasses.add(name); - if (DEBUG_CLASSLOADING) - { - FMLLog.log(Level.FINEST, e, "Exception encountered attempting classloading of %s", name); - } - throw new ClassNotFoundException(name, e); - } - } - - private void saveTransformedClass(byte[] data, String transformedName) - { - if (!DEBUG_CLASSLOADING_SAVE || temp_folder == null) - { - return; - } - - File outFile = new File(temp_folder, transformedName.replace('.', File.separatorChar) + ".class"); - File outDir = outFile.getParentFile(); - - if (!outDir.exists()) - { - outDir.mkdirs(); - } - - if (outFile.exists()) - { - outFile.delete(); - } - - try - { - FMLRelaunchLog.fine("Saving transformed class \"%s\" to \"%s\"", transformedName, outFile.getAbsolutePath().replace('\\', '/')); - OutputStream output = new FileOutputStream(outFile); - output.write(data); - output.close(); - } - catch(IOException ex) - { - FMLRelaunchLog.log(Level.WARNING, ex, "Could not save transformed class \"%s\"", transformedName); - } - } - - private String untransformName(String name) - { - if (renameTransformer != null) - { - return renameTransformer.unmapClassName(name); - } - else - { - return name; - } - } - - private String transformName(String name) - { - if (renameTransformer != null) - { - return renameTransformer.remapClassName(name); - } - else - { - return name; - } - } - - private boolean isSealed(String path, Manifest man) - { - Attributes attr = man.getAttributes(path); - String sealed = null; - if (attr != null) { - sealed = attr.getValue(Name.SEALED); - } - if (sealed == null) { - if ((attr = man.getMainAttributes()) != null) { - sealed = attr.getValue(Name.SEALED); - } - } - return "true".equalsIgnoreCase(sealed); - } - - private URLConnection findCodeSourceConnectionFor(String name) - { - URL res = findResource(name); - if (res != null) - { - try - { - return res.openConnection(); - } - catch (IOException e) - { - throw new RuntimeException(e); - } - } - else - { - return null; - } - } - - private byte[] runTransformers(String name, String transformedName, byte[] basicClass) - { - if (DEBUG_CLASSLOADING_FINER) - { - FMLRelaunchLog.finest("Beginning transform of %s (%s) Start Length: %d", name, transformedName, (basicClass == null ? 0 : basicClass.length)); - for (IClassTransformer transformer : transformers) - { - String transName = transformer.getClass().getName(); - FMLRelaunchLog.finest("Before Transformer %s: %d", transName, (basicClass == null ? 0 : basicClass.length)); - basicClass = transformer.transform(name, transformedName, basicClass); - FMLRelaunchLog.finest("After Transformer %s: %d", transName, (basicClass == null ? 0 : basicClass.length)); - } - FMLRelaunchLog.finest("Ending transform of %s (%s) Start Length: %d", name, transformedName, (basicClass == null ? 0 : basicClass.length)); - } - else - { - for (IClassTransformer transformer : transformers) - { - basicClass = transformer.transform(name, transformedName, basicClass); - } - } - return basicClass; - } - - @Override - public void addURL(URL url) - { - super.addURL(url); - sources.add(url); - } - - public List getSources() - { - return sources; - } - - - private byte[] readFully(InputStream stream) - { - try - { - byte[] buf = loadBuffer.get(); - if (buf == null) - { - loadBuffer.set(new byte[1 << 12]); - buf = loadBuffer.get(); - } - - int r, totalLength = 0; - while ((r = stream.read(buf, totalLength, buf.length - totalLength)) != -1) - { - totalLength += r; - if (totalLength >= buf.length - 1) - { - byte[] oldbuf = buf; - buf = new byte[ oldbuf.length + (1 << 12 )]; - System.arraycopy(oldbuf, 0, buf, 0, oldbuf.length); - } - } - - byte[] result = new byte[totalLength]; - System.arraycopy(buf, 0, result, 0, totalLength); - return result; - } - catch (Throwable t) - { - FMLRelaunchLog.log(Level.WARNING, t, "Problem loading class"); - return new byte[0]; - } - } - - public List getTransformers() - { - return Collections.unmodifiableList(transformers); - } - - private void addClassLoaderExclusion(String toExclude) - { - classLoaderExceptions.add(toExclude); - } - - void addTransformerExclusion(String toExclude) - { - transformerExceptions.add(toExclude); - } - - public byte[] getClassBytes(String name) throws IOException - { - if (name.indexOf('.') == -1) - { - for (String res : RESERVED) - { - if (name.toUpperCase(Locale.ENGLISH).startsWith(res)) - { - byte[] data = getClassBytes("_" + name); - if (data != null) - { - return data; - } - } - } - } - - InputStream classStream = null; - try - { - URL classResource = findResource(name.replace('.', '/').concat(".class")); - if (classResource == null) - { - if (DEBUG_CLASSLOADING) - { - FMLLog.finest("Failed to find class resource %s", name.replace('.', '/').concat(".class")); - } - return null; - } - classStream = classResource.openStream(); - if (DEBUG_CLASSLOADING) - { - FMLLog.finest("Loading class %s from resource %s", name, classResource.toString()); - } - return readFully(classStream); - } - finally - { - if (classStream != null) - { - try - { - classStream.close(); - } - catch (IOException e) - { - // Swallow the close exception - } - } - } - } -} diff --git a/fml/common/cpw/mods/fml/relauncher/ServerLaunchWrapper.java b/fml/common/cpw/mods/fml/relauncher/ServerLaunchWrapper.java index 92bcc42ea4..6975689c9e 100644 --- a/fml/common/cpw/mods/fml/relauncher/ServerLaunchWrapper.java +++ b/fml/common/cpw/mods/fml/relauncher/ServerLaunchWrapper.java @@ -4,6 +4,9 @@ import java.io.File; import java.net.URLClassLoader; import java.util.logging.Level; +import net.minecraft.launchwrapper.Launch; +import net.minecraft.launchwrapper.LaunchClassLoader; + import com.google.common.base.Throwables; public class ServerLaunchWrapper { @@ -23,42 +26,7 @@ public class ServerLaunchWrapper { private void run(String[] args) { - File minecraftHome = new File("."); - FMLRelaunchLog.minecraftHome = minecraftHome; - FMLRelauncher.logFileNamePattern = "ForgeModLoader-server-%g.log"; - FMLRelauncher.side = "SERVER"; - URLClassLoader ucl = (URLClassLoader) getClass().getClassLoader(); - - RelaunchClassLoader classLoader = new RelaunchClassLoader(ucl.getURLs()); - - RelaunchLibraryManager.downloadMonitor = new DummyDownloader(); - Class server; - FMLInjectionData.build(minecraftHome, classLoader); - FMLRelaunchLog.info("Forge Mod Loader version %s.%s.%s.%s for Minecraft %s loading", FMLInjectionData.major, FMLInjectionData.minor, - FMLInjectionData.rev, FMLInjectionData.build, FMLInjectionData.mccversion, FMLInjectionData.mcpversion); - FMLRelaunchLog.info("Java is %s, version %s, running on %s:%s:%s, installed at %s", System.getProperty("java.vm.name"), System.getProperty("java.version"), System.getProperty("os.name"), System.getProperty("os.arch"), System.getProperty("os.version"), System.getProperty("java.home")); - FMLRelaunchLog.fine("Java classpath at launch is %s", System.getProperty("java.class.path")); - FMLRelaunchLog.fine("Java library path at launch is %s", System.getProperty("java.library.path")); - - try - { - RelaunchLibraryManager.handleLaunch(minecraftHome, classLoader); - } - catch (Throwable t) - { - throw Throwables.propagate(t); - } - - server = ReflectionHelper.getClass(classLoader, "net.minecraft.server.MinecraftServer"); - try - { - ReflectionHelper.findMethod(server, null, new String[] { "main" }, String[].class).invoke(null, (Object)args); - } - catch (Exception t) - { - throw Throwables.propagate(t); - } - + Launch.main(args); } } diff --git a/fml/common/cpw/mods/fml/relauncher/Side.java b/fml/common/cpw/mods/fml/relauncher/Side.java index 83f23a1c71..b1bda1d904 100644 --- a/fml/common/cpw/mods/fml/relauncher/Side.java +++ b/fml/common/cpw/mods/fml/relauncher/Side.java @@ -5,7 +5,7 @@ * are made available under the terms of the GNU Lesser Public License v2.1 * which accompanies this distribution, and is available at * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html - * + * * Contributors: * cpw - implementation */ @@ -13,7 +13,7 @@ package cpw.mods.fml.relauncher; public enum Side { - CLIENT, SERVER, BUKKIT; + CLIENT, SERVER; /** * @return If this is the server environment diff --git a/fml/common/cpw/mods/fml/relauncher/SideOnly.java b/fml/common/cpw/mods/fml/relauncher/SideOnly.java index 9edf009fdb..3a066034ee 100644 --- a/fml/common/cpw/mods/fml/relauncher/SideOnly.java +++ b/fml/common/cpw/mods/fml/relauncher/SideOnly.java @@ -5,7 +5,7 @@ * are made available under the terms of the GNU Lesser Public License v2.1 * which accompanies this distribution, and is available at * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html - * + * * Contributors: * cpw - implementation */ @@ -17,7 +17,22 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import cpw.mods.fml.common.SidedProxy; + +/** + * Marks the associated element as being only available on a certain {@link Side}. This is + * generally meant for internal Forge and FML use only and should only be used on mod classes + * when other more common mechanisms, such as using a {@link SidedProxy} fail to work. + * + * Note, this will only apply to the direct element marked. This code: + * @SideOnly public MyField field = new MyField(); will not work, as the initializer + * is a separate piece of code to the actual field declaration, and will not be able to find + * it's field on the wrong side. + * + * @author cpw + * + */ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.CONSTRUCTOR}) public @interface SideOnly diff --git a/fml/patches/minecraft/net/minecraft/client/Minecraft.java.patch b/fml/patches/minecraft/net/minecraft/client/Minecraft.java.patch index 3b8f534d0c..ad5b9e1829 100644 --- a/fml/patches/minecraft/net/minecraft/client/Minecraft.java.patch +++ b/fml/patches/minecraft/net/minecraft/client/Minecraft.java.patch @@ -1,18 +1,16 @@ --- ../src-base/minecraft/net/minecraft/client/Minecraft.java +++ ../src-work/minecraft/net/minecraft/client/Minecraft.java -@@ -1,5 +1,11 @@ +@@ -1,5 +1,9 @@ package net.minecraft.client; +import cpw.mods.fml.client.FMLClientHandler; +import cpw.mods.fml.common.FMLCommonHandler; +import cpw.mods.fml.common.registry.GameData; +import cpw.mods.fml.common.registry.ItemData; -+import cpw.mods.fml.relauncher.ArgsWrapper; -+import cpw.mods.fml.relauncher.FMLRelauncher; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import java.awt.BorderLayout; -@@ -115,6 +121,8 @@ +@@ -115,6 +119,8 @@ import org.lwjgl.opengl.PixelFormat; import org.lwjgl.util.glu.GLU; @@ -21,7 +19,7 @@ @SideOnly(Side.CLIENT) public abstract class Minecraft implements Runnable, IPlayerUsage { -@@ -299,6 +307,8 @@ +@@ -299,6 +305,8 @@ this.field_71466_p = new FontRenderer(this.field_71474_y, "/font/default.png", this.field_71446_o, false); this.field_71464_q = new FontRenderer(this.field_71474_y, "/font/alternate.png", this.field_71446_o, false); @@ -30,7 +28,7 @@ if (this.field_71474_y.field_74363_ab != null) { StringTranslate.func_74808_a().func_74810_a(this.field_71474_y.field_74363_ab, false); -@@ -334,6 +344,8 @@ +@@ -334,6 +342,8 @@ GL11.glViewport(0, 0, this.field_71443_c, this.field_71440_d); this.field_71452_i = new EffectRenderer(this.field_71441_e, this.field_71446_o); @@ -39,7 +37,7 @@ try { this.field_71430_V = new ThreadDownloadResources(this.field_71412_D, this); -@@ -362,6 +374,8 @@ +@@ -362,6 +372,8 @@ { this.func_71352_k(); } @@ -48,7 +46,7 @@ } private void func_71357_I() throws LWJGLException -@@ -723,9 +737,11 @@ +@@ -723,9 +735,11 @@ if (!this.field_71454_w) { @@ -60,7 +58,7 @@ } GL11.glFlush(); -@@ -1255,10 +1271,14 @@ +@@ -1255,10 +1269,14 @@ public void func_71407_l() { @@ -75,7 +73,7 @@ this.field_71424_I.func_76320_a("stats"); this.field_71413_E.func_77449_e(); -@@ -1716,6 +1736,8 @@ +@@ -1716,6 +1734,8 @@ this.field_71453_ak.func_74428_b(); } @@ -84,7 +82,7 @@ this.field_71424_I.func_76319_b(); this.field_71423_H = func_71386_F(); } -@@ -1754,8 +1776,27 @@ +@@ -1754,8 +1774,27 @@ } this.field_71413_E.func_77450_a(StatList.field_75936_f, 1); @@ -112,16 +110,3 @@ this.field_71455_al = true; this.field_71461_s.func_73720_a(StatCollector.func_74838_a("menu.loadingLevel")); -@@ -1977,6 +2018,12 @@ - - public static void main(String[] p_main_0_) - { -+ FMLRelauncher.handleClientRelaunch(new ArgsWrapper(p_main_0_)); -+ } -+ -+ public static void fmlReentry(ArgsWrapper wrapper) -+ { -+ String[] p_main_0_ = wrapper.args; - HashMap hashmap = new HashMap(); - boolean flag = false; - boolean flag1 = true; diff --git a/fml/patches/minecraft/net/minecraft/client/MinecraftApplet.java.patch b/fml/patches/minecraft/net/minecraft/client/MinecraftApplet.java.patch deleted file mode 100644 index eddb62a7c3..0000000000 --- a/fml/patches/minecraft/net/minecraft/client/MinecraftApplet.java.patch +++ /dev/null @@ -1,33 +0,0 @@ ---- ../src-base/minecraft/net/minecraft/client/MinecraftApplet.java -+++ ../src-work/minecraft/net/minecraft/client/MinecraftApplet.java -@@ -1,5 +1,6 @@ - package net.minecraft.client; - -+import cpw.mods.fml.relauncher.FMLRelauncher; - import cpw.mods.fml.relauncher.Side; - import cpw.mods.fml.relauncher.SideOnly; - import java.applet.Applet; -@@ -15,6 +16,11 @@ - private Thread field_71482_c = null; - - public void init() -+ { -+ FMLRelauncher.appletEntry(this); -+ } -+ -+ public void fmlInitReentry() - { - this.field_71483_a = new CanvasMinecraftApplet(this); - boolean flag = "true".equalsIgnoreCase(this.getParameter("fullscreen")); -@@ -63,6 +69,11 @@ - - public void start() - { -+ FMLRelauncher.appletStart(this); -+ } -+ -+ public void fmlStartReentry() -+ { - if (this.field_71481_b != null) - { - this.field_71481_b.field_71445_n = false; diff --git a/fml/patches/minecraft/net/minecraft/server/MinecraftServer.java.patch b/fml/patches/minecraft/net/minecraft/server/MinecraftServer.java.patch index 2dfdd271a4..5dce5d643a 100644 --- a/fml/patches/minecraft/net/minecraft/server/MinecraftServer.java.patch +++ b/fml/patches/minecraft/net/minecraft/server/MinecraftServer.java.patch @@ -1,15 +1,13 @@ --- ../src-base/minecraft/net/minecraft/server/MinecraftServer.java +++ ../src-work/minecraft/net/minecraft/server/MinecraftServer.java -@@ -1,5 +1,8 @@ +@@ -1,5 +1,6 @@ package net.minecraft.server; +import cpw.mods.fml.common.FMLCommonHandler; -+import cpw.mods.fml.relauncher.ArgsWrapper; -+import cpw.mods.fml.relauncher.FMLRelauncher; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import java.awt.GraphicsEnvironment; -@@ -352,7 +355,11 @@ +@@ -352,7 +353,11 @@ { if (this.func_71197_b()) { @@ -21,7 +19,7 @@ for (long j = 0L; this.field_71317_u; this.field_71296_Q = true) { -@@ -391,6 +398,7 @@ +@@ -391,6 +396,7 @@ Thread.sleep(1L); } @@ -29,7 +27,7 @@ } else { -@@ -399,6 +407,10 @@ +@@ -399,6 +405,10 @@ } catch (Throwable throwable) { @@ -40,7 +38,7 @@ throwable.printStackTrace(); this.func_98033_al().func_98234_c("Encountered an unexpected exception " + throwable.getClass().getSimpleName(), throwable); CrashReport crashreport = null; -@@ -429,6 +441,10 @@ +@@ -429,6 +439,10 @@ { try { @@ -51,7 +49,7 @@ this.func_71260_j(); this.field_71316_v = true; } -@@ -438,6 +454,8 @@ +@@ -438,6 +452,8 @@ } finally { @@ -60,7 +58,7 @@ this.func_71240_o(); } } -@@ -454,8 +472,10 @@ +@@ -454,8 +470,10 @@ public void func_71217_p() { @@ -71,7 +69,7 @@ ++this.field_71315_w; if (this.field_71295_T) -@@ -501,6 +521,7 @@ +@@ -501,6 +519,7 @@ this.field_71304_b.func_76319_b(); this.field_71304_b.func_76319_b(); @@ -79,7 +77,7 @@ } public void func_71190_q() -@@ -528,6 +549,7 @@ +@@ -528,6 +547,7 @@ } this.field_71304_b.func_76320_a("tick"); @@ -87,7 +85,7 @@ CrashReport crashreport; try -@@ -552,6 +574,7 @@ +@@ -552,6 +572,7 @@ throw new ReportedException(crashreport); } @@ -95,7 +93,7 @@ this.field_71304_b.func_76319_b(); this.field_71304_b.func_76320_a("tracker"); worldserver.func_73039_n().func_72788_a(); -@@ -679,7 +702,7 @@ +@@ -679,7 +700,7 @@ public String getServerModName() { @@ -104,17 +102,3 @@ } public CrashReport func_71230_b(CrashReport p_71230_1_) -@@ -1137,6 +1160,13 @@ - @SideOnly(Side.SERVER) - public static void main(String[] p_main_0_) - { -+ FMLRelauncher.handleServerRelaunch(new ArgsWrapper(p_main_0_)); -+ } -+ -+ @SideOnly(Side.SERVER) -+ public static void fmlReentry(ArgsWrapper wrap) -+ { -+ String[] p_main_0_ = wrap.args; - StatList.func_75919_a(); - ILogAgent ilogagent = null; -