Merge in binpatch and use launcher

This commit is contained in:
Christian 2013-06-14 17:21:49 -04:00
parent 21240df8bc
commit 07a5efe612
23 changed files with 414 additions and 1103 deletions

View file

@ -15,8 +15,8 @@
<arg value="${mcp.home}" /> <arg value="${mcp.home}" />
</exec> </exec>
<propertyfile file="fmlversion.properties"> <propertyfile file="fmlversion.properties">
<entry key="fmlbuild.build.number" type="int" value="${version.build}"/> <entry key="fmlbuild.build.number" type="int" value="${version.build}" />
<entry key="fmlbuild.deobfuscation.hash" type="string" value="${deobf.checksum}"/> <entry key="fmlbuild.deobfuscation.hash" type="string" value="${deobf.checksum}" />
</propertyfile> </propertyfile>
</target> </target>
@ -34,11 +34,11 @@
<os family="Windows" /> <os family="Windows" />
</condition> </condition>
<condition property="mcp.exists"> <condition property="mcp.exists">
<available file="${mcp.home}/runtime/commands.py"/> <available file="${mcp.home}/runtime/commands.py" />
</condition>
<condition property="signature.exists">
<available file="${env.JENKINS_HOME}/fmlsigned.properties" />
</condition> </condition>
<condition property="signature.exists">
<available file="${env.JENKINS_HOME}/fmlsigned.properties"/>
</condition>
<property name="mcp.obfoutput" location="${mcp.home}/reobf" /> <property name="mcp.obfoutput" location="${mcp.home}/reobf" />
<property name="client.mcp.obfoutput" location="${mcp.obfoutput}/minecraft" /> <property name="client.mcp.obfoutput" location="${mcp.obfoutput}/minecraft" />
<property name="mcp.srcdir" location="${mcp.home}/src" /> <property name="mcp.srcdir" location="${mcp.home}/src" />
@ -54,7 +54,7 @@
<condition property="version.build" value="${env.BUILD_NUMBER}" else="1"> <condition property="version.build" value="${env.BUILD_NUMBER}" else="1">
<isset property="env.BUILD_NUMBER" /> <isset property="env.BUILD_NUMBER" />
</condition> </condition>
<available file="eclipse" property="eclipse.exists"/> <available file="eclipse" property="eclipse.exists" />
</target> </target>
<target name="makeversion" depends="buildenvsetup"> <target name="makeversion" depends="buildenvsetup">
@ -89,19 +89,19 @@
<arg value="${mcp.home}/runtime/reobfuscate.py" /> <arg value="${mcp.home}/runtime/reobfuscate.py" />
</exec> </exec>
<fail message="Reobfuscation failed"> <fail message="Reobfuscation failed">
<condition> <condition>
<not> <not>
<and> <and>
<available file="${mcp.home}/temp/client.md5"/> <available file="${mcp.home}/temp/client.md5" />
<available file="${mcp.home}/temp/client_reobf.md5"/> <available file="${mcp.home}/temp/client_reobf.md5" />
</and> </and>
</not> </not>
</condition> </condition>
</fail> </fail>
<exec executable="${python.exe}" dir="${mcp.home}"> <exec executable="${python.exe}" dir="${mcp.home}">
<arg value="${basedir}/generatechangedfilelist.py"/> <arg value="${basedir}/generatechangedfilelist.py" />
<arg value="${mcp.home}"/> <arg value="${mcp.home}" />
<arg value="${basedir}/difflist.txt"/> <arg value="${basedir}/difflist.txt" />
</exec> </exec>
</target> </target>
@ -110,11 +110,11 @@
<arg value="${mcp.home}/runtime/recompile.py" /> <arg value="${mcp.home}/runtime/recompile.py" />
</exec> </exec>
<fail message="Compilation failed"> <fail message="Compilation failed">
<condition> <condition>
<not> <not>
<available file="${mcp.home}/bin/minecraft/net/minecraft/client/Minecraft.class"/> <available file="${mcp.home}/bin/minecraft/net/minecraft/client/Minecraft.class" />
</not> </not>
</condition> </condition>
</fail> </fail>
</target> </target>
@ -140,19 +140,19 @@
<mkdir dir="${basedir}/target" /> <mkdir dir="${basedir}/target" />
<jar destfile="${basedir}/target/${universal.jarname}.zip" duplicate="preserve"> <jar destfile="${basedir}/target/${universal.jarname}.zip" duplicate="preserve">
<manifest> <manifest>
<attribute name="Main-Class" value="cpw.mods.fml.relauncher.ServerLaunchWrapper"/> <attribute name="Main-Class" value="cpw.mods.fml.relauncher.ServerLaunchWrapper" />
<attribute name="Class-Path" value="minecraft_server.jar:lib/guava-14.0-rc3.jar:lib/bcprov-jdk15on-148-src.zip:lib/asm-debug-all-4.1.jar:lib/scala-library.jar:lib/argo-3.2-src.jar"/> <attribute name="Class-Path" value="minecraft_server.jar:lib/guava-14.0-rc3.jar:lib/bcprov-jdk15on-148-src.zip:lib/asm-debug-all-4.1.jar:lib/scala-library.jar:lib/argo-3.2-src.jar" />
</manifest> </manifest>
<fileset dir="${client.mcp.obfoutput}" includes="**/*.class" excludes="*.class"/> <fileset dir="${client.mcp.obfoutput}" includes="**/*.class" excludes="*.class" />
</jar> </jar>
<antcall target="signjar"/> <antcall target="signjar" />
<zip update="true" destfile="${basedir}/target/${universal.jarname}.zip" > <zip update="true" destfile="${basedir}/target/${universal.jarname}.zip">
<fileset dir="${client.mcp.obfoutput}" includes="*.class"/> <fileset dir="${client.mcp.obfoutput}" includes="*.class" />
<zipfileset dir="${basedir}" includes="fmlversion.properties"/> <zipfileset dir="${basedir}" includes="fmlversion.properties" />
<zipfileset dir="${basedir}" includes="LICENSE-fml.txt" /> <zipfileset dir="${basedir}" includes="LICENSE-fml.txt" />
<zipfileset dir="${common.src.dir}" includes="mcpmod.info" /> <zipfileset dir="${common.src.dir}" includes="mcpmod.info" />
<zipfileset dir="${client.src.dir}" includes="mcp.png" /> <zipfileset dir="${client.src.dir}" includes="mcp.png" />
<zipfileset dir="${basedir}" includes="install/CREDITS-fml.txt" fullpath="CREDITS-fml.txt"/> <zipfileset dir="${basedir}" includes="install/CREDITS-fml.txt" fullpath="CREDITS-fml.txt" />
<zipfileset dir="${common.src.dir}" includes="*.cfg" /> <zipfileset dir="${common.src.dir}" includes="*.cfg" />
<mappedresources> <mappedresources>
<concat> <concat>
@ -205,25 +205,25 @@
</target> </target>
<target name="build-deobf-data" depends="makeversion"> <target name="build-deobf-data" depends="makeversion">
<mkdir dir="build-tmp-deobf"/> <mkdir dir="build-tmp-deobf" />
<copy todir="build-tmp-deobf"> <copy todir="build-tmp-deobf">
<mappedresources> <mappedresources>
<fileset dir="${mcp.home}/conf" includes="packaged.srg"/> <fileset dir="${mcp.home}/conf" includes="packaged.srg" />
<globmapper from="packaged.srg" to="joined.srg"/> <globmapper from="packaged.srg" to="joined.srg" />
</mappedresources> </mappedresources>
</copy> </copy>
<touch millis="0" file="build-tmp-deobf/joined.srg"/> <touch millis="0" file="build-tmp-deobf/joined.srg" />
<zip file="deobfuscation_data_${version.minecraft}.zip" encoding="UTF-8"> <zip file="deobfuscation_data_${version.minecraft}.zip" encoding="UTF-8">
<fileset dir="build-tmp-deobf" includes="joined.srg"/> <fileset dir="build-tmp-deobf" includes="joined.srg" />
</zip> </zip>
<checksum algorithm="SHA1" property="deobf.checksum" file="deobfuscation_data_${version.minecraft}.zip"/> <checksum algorithm="SHA1" property="deobf.checksum" file="deobfuscation_data_${version.minecraft}.zip" />
<antcall target="writeversion"/> <antcall target="writeversion" />
<delete dir="build-tmp-deobf" /> <delete dir="build-tmp-deobf" />
</target> </target>
<target name="build" depends="buildenvsetup,merge-client,merge-common,build-deobf-data,build-universal,build-source-pack" /> <target name="build" depends="buildenvsetup,merge-client,merge-common,build-deobf-data,build-universal,build-source-pack" />
<target name="jenkinsbuild" depends="buildenvsetup,jenkinsfmldecompile,patch,build"/> <target name="jenkinsbuild" depends="buildenvsetup,jenkinsfmldecompile,patch,build" />
<target name="patch" depends="buildenvsetup"> <target name="patch" depends="buildenvsetup">
<exec executable="${python.exe}" dir="${basedir}"> <exec executable="${python.exe}" dir="${basedir}">
@ -242,25 +242,25 @@
</condition> </condition>
<fail if="do.not.continue">You have decided not to continue. This script will stop now.</fail> <fail if="do.not.continue">You have decided not to continue. This script will stop now.</fail>
<echo>Preparing the MCP environment at ${mcp.home}</echo> <echo>Preparing the MCP environment at ${mcp.home}</echo>
<antcall target="fmldecompile"/> <antcall target="fmldecompile" />
<echo>Moving old patched sources at ${patch.mcp.srcdir} out of the way</echo> <echo>Moving old patched sources at ${patch.mcp.srcdir} out of the way</echo>
<move todir="${mcp.home}/src-work${timestamp}" failonerror="false" verbose="true"> <move todir="${mcp.home}/src-work${timestamp}" failonerror="false" verbose="true">
<fileset dir="${patch.mcp.srcdir}"/> <fileset dir="${patch.mcp.srcdir}" />
</move> </move>
<echo>Deleting old patch references at ${clean.mcp.srcdir}</echo> <echo>Deleting old patch references at ${clean.mcp.srcdir}</echo>
<delete dir="${clean.mcp.srcdir}" failonerror="false"/> <delete dir="${clean.mcp.srcdir}" failonerror="false" />
<echo>Creating new patch references at ${clean.mcp.srcdir}</echo> <echo>Creating new patch references at ${clean.mcp.srcdir}</echo>
<copy todir="${clean.mcp.srcdir}"> <copy todir="${clean.mcp.srcdir}">
<fileset dir="${mcp.srcdir}"/> <fileset dir="${mcp.srcdir}" />
</copy> </copy>
<antcall target="cleanargo"/> <antcall target="cleanargo" />
<antcall target="patch"/> <antcall target="patch" />
<echo>Creating clean patched references at ${patch.mcp.srcdir}</echo> <echo>Creating clean patched references at ${patch.mcp.srcdir}</echo>
<copy todir="${patch.mcp.srcdir}"> <copy todir="${patch.mcp.srcdir}">
<fileset dir="${mcp.srcdir}"/> <fileset dir="${mcp.srcdir}" />
</copy> </copy>
<antcall target="writeversion"/> <antcall target="writeversion" />
<antcall target="makeeclipse"/> <antcall target="makeeclipse" />
<echo>Setup complete! You should now be able to open ${basedir}/eclipse as a workspace in eclipse and import/refresh the FML project</echo> <echo>Setup complete! You should now be able to open ${basedir}/eclipse as a workspace in eclipse and import/refresh the FML project</echo>
</target> </target>
@ -284,45 +284,45 @@
<target name="repatch" depends="buildenvsetup,checkpatches"> <target name="repatch" depends="buildenvsetup,checkpatches">
<echo>Moving old patched sources at ${mcp.home}/src-work out of the way</echo> <echo>Moving old patched sources at ${mcp.home}/src-work out of the way</echo>
<move todir="${mcp.home}/src-work${timestamp}" failonerror="false" verbose="true"> <move todir="${mcp.home}/src-work${timestamp}" failonerror="false" verbose="true">
<fileset dir="${patch.mcp.srcdir}"/> <fileset dir="${patch.mcp.srcdir}" />
</move> </move>
<delete dir="${mcp.srcdir}"/> <delete dir="${mcp.srcdir}" />
<copy todir="${mcp.srcdir}"> <copy todir="${mcp.srcdir}">
<fileset dir="${clean.mcp.srcdir}"/> <fileset dir="${clean.mcp.srcdir}" />
</copy> </copy>
<antcall target="cleanargo"/> <antcall target="cleanargo" />
<antcall target="patch"/> <antcall target="patch" />
<copy todir="${patch.mcp.srcdir}"> <copy todir="${patch.mcp.srcdir}">
<fileset dir="${mcp.srcdir}"/> <fileset dir="${mcp.srcdir}" />
</copy> </copy>
</target> </target>
<target name="repatchclean" depends="buildenvsetup"> <target name="repatchclean" depends="buildenvsetup">
<delete dir="${mcp.srcdir}"/> <delete dir="${mcp.srcdir}" />
<copy todir="${mcp.srcdir}"> <copy todir="${mcp.srcdir}">
<fileset dir="${clean.mcp.srcdir}"/> <fileset dir="${clean.mcp.srcdir}" />
</copy> </copy>
<antcall target="cleanargo"/> <antcall target="cleanargo" />
<antcall target="patch"/> <antcall target="patch" />
</target> </target>
<target name="cleanargo" depends="buildenvsetup"> <target name="cleanargo" depends="buildenvsetup">
<delete dir="${client.mcp.srcdir}/argo"/> <delete dir="${client.mcp.srcdir}/argo" />
<delete dir="${client.mcp.srcdir}/org"/> <delete dir="${client.mcp.srcdir}/org" />
</target> </target>
<target name="checkpatches" depends="buildenvsetup"> <target name="checkpatches" depends="buildenvsetup">
<uptodate property="checkUptodate.uptodate"> <uptodate property="checkUptodate.uptodate">
<srcfiles dir="${patch.mcp.srcdir}" includes="**/*.java"> <srcfiles dir="${patch.mcp.srcdir}" includes="**/*.java">
<present targetdir="${patch.src.dir}"> <present targetdir="${patch.src.dir}">
<globmapper from="*.java" to="*.java.patch"/> <globmapper from="*.java" to="*.java.patch" />
</present> </present>
</srcfiles> </srcfiles>
<globmapper from="*.java" to="${patch.src.dir}/*.java.patch"/> <globmapper from="*.java" to="${patch.src.dir}/*.java.patch" />
</uptodate> </uptodate>
<fail unless="checkUptodate.uptodate"> <fail unless="checkUptodate.uptodate">
A patch is out of date. Update your patches! A patch is out of date. Update your patches!
@ -332,8 +332,8 @@
<target name="updatepatches" depends="buildenvsetup"> <target name="updatepatches" depends="buildenvsetup">
<exec executable="${python.exe}" dir="${basedir}"> <exec executable="${python.exe}" dir="${basedir}">
<arg value="${basedir}/update_patches.py" /> <arg value="${basedir}/update_patches.py" />
<arg value="${mcp.home}"/> <arg value="${mcp.home}" />
<arg value="${basedir}"/> <arg value="${basedir}" />
</exec> </exec>
</target> </target>
@ -341,30 +341,43 @@
<echo> <echo>
Extracting fresh eclipse workspace to ${basedir}/eclipse Extracting fresh eclipse workspace to ${basedir}/eclipse
</echo> </echo>
<unzip src="${basedir}/eclipse-workspace-dev.zip" dest="${basedir}"/> <unzip src="${basedir}/eclipse-workspace-dev.zip" dest="${basedir}" />
</target> </target>
<target name="makerenamedsource" depends="buildenvsetup,repatch,merge-client,merge-common,reobfuscate"> <target name="makerenamedsource" depends="buildenvsetup,repatch,merge-client,merge-common,reobfuscate">
<copy todir="${tmp.mcp.srcdir}"> <copy todir="${tmp.mcp.srcdir}">
<fileset dir="${mcp.srcdir}"/> <fileset dir="${mcp.srcdir}" />
</copy> </copy>
<exec executable="${python.exe}" dir="${mcp.home}"> <exec executable="${python.exe}" dir="${mcp.home}">
<arg value="${mcp.home}/runtime/updatenames.py" /> <arg value="${mcp.home}/runtime/updatenames.py" />
<arg value="-f" /> <arg value="-f" />
</exec> </exec>
<copy todir="${renamed.mcp.srcdir}"> <copy todir="${renamed.mcp.srcdir}">
<fileset dir="${mcp.srcdir}"/> <fileset dir="${mcp.srcdir}" />
</copy> </copy>
<move todir="${mcp.srcdir}"> <move todir="${mcp.srcdir}">
<fileset dir="${tmp.mcp.srcdir}"/> <fileset dir="${tmp.mcp.srcdir}" />
</move> </move>
</target> </target>
<target name="signjar" depends="buildenvsetup,makeversion" if="signature.exists"> <target name="signjar" depends="buildenvsetup,makeversion" if="signature.exists">
<condition property="universal.jarname" value="${modname}-universal-${version.minecraft}-${version}" else="${modname}-universal-${version.minecraft}-${version}-${version.branch}"> <condition property="universal.jarname" value="${modname}-universal-${version.minecraft}-${version}" else="${modname}-universal-${version.minecraft}-${version}-${version.branch}">
<equals arg1="${version.branch}" arg2="master" /> <equals arg1="${version.branch}" arg2="master" />
</condition> </condition>
<property file="${env.JENKINS_HOME}/fmlsigned.properties" prefix="sign"/> <property file="${env.JENKINS_HOME}/fmlsigned.properties" prefix="sign" />
<echo>${env.JENKINS_HOME} ${universal.jarname} ${sign.KEYPASS}</echo> <echo>${env.JENKINS_HOME} ${universal.jarname} ${sign.KEYPASS}</echo>
<signjar alias="FML" jar="${basedir}/target/${universal.jarname}.zip" keypass="${sign.KEYPASS}" keystore="${env.JENKINS_HOME}/${sign.KEYSTORE}" storepass="${sign.STOREPASS}" verbose="true"/> <signjar alias="FML" jar="${basedir}/target/${universal.jarname}.zip" keypass="${sign.KEYPASS}" keystore="${env.JENKINS_HOME}/${sign.KEYSTORE}" storepass="${sign.STOREPASS}" verbose="true" />
</target>
<target name="makebinpatches">
<java classname="cpw.mods.fml.patcher.GenDiffSet">
<classpath>
<fileset dir="${mcp.home}/lib" includes="guava-14.0-rc3.jar"/>
<dirset dir="${mcp.obfoutput}"/>
</classpath>
<arg path="${mcp.home}/jars/bin/minecraft.jar.backup"/>
<arg path="${mcp.home}/jars/bin/minecraft.jar.backup"/>
<arg path="${mcp.obfoutput}"/>
<arg path="${basedir}/deobfuscation_data_${version.minecraft}.zip"/>
<arg path="${basedir}/binpatch/client"/>
</java>
</target> </target>
</project> </project>

View file

@ -5,7 +5,7 @@
* are made available under the terms of the GNU Lesser Public License v2.1 * are made available under the terms of the GNU Lesser Public License v2.1
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* *
* Contributors: * Contributors:
* cpw - implementation * cpw - implementation
*/ */
@ -20,12 +20,13 @@ import java.net.URLClassLoader;
import java.util.List; import java.util.List;
import java.util.logging.Level; import java.util.logging.Level;
import net.minecraft.launchwrapper.LaunchClassLoader;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import cpw.mods.fml.common.asm.ASMTransformer; import cpw.mods.fml.common.asm.ASMTransformer;
import cpw.mods.fml.common.asm.transformers.AccessTransformer; import cpw.mods.fml.common.asm.transformers.AccessTransformer;
import cpw.mods.fml.common.modloader.BaseModProxy; 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 * 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 public class ModClassLoader extends URLClassLoader
{ {
private static final List<String> STANDARD_LIBRARIES = ImmutableList.of("jinput.jar", "lwjgl.jar", "lwjgl_util.jar"); private static final List<String> STANDARD_LIBRARIES = ImmutableList.of("jinput.jar", "lwjgl.jar", "lwjgl_util.jar");
private RelaunchClassLoader mainClassLoader; private LaunchClassLoader mainClassLoader;
public ModClassLoader(ClassLoader parent) { public ModClassLoader(ClassLoader parent) {
super(new URL[0], null); super(new URL[0], null);
this.mainClassLoader = (RelaunchClassLoader)parent; this.mainClassLoader = (LaunchClassLoader)parent;
} }
public void addFile(File modFile) throws MalformedURLException public void addFile(File modFile) throws MalformedURLException

View file

@ -35,6 +35,8 @@ import java.util.Map;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
import net.minecraft.launchwrapper.LaunchClassLoader;
import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor; 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.CertificateHelper;
import cpw.mods.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper; import cpw.mods.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper;
import cpw.mods.fml.common.patcher.ClassPatchManager; import cpw.mods.fml.common.patcher.ClassPatchManager;
import cpw.mods.fml.relauncher.FMLLaunchHandler;
import cpw.mods.fml.relauncher.FMLRelaunchLog; import cpw.mods.fml.relauncher.FMLRelaunchLog;
import cpw.mods.fml.relauncher.FMLRelauncher;
import cpw.mods.fml.relauncher.IFMLCallHook; import cpw.mods.fml.relauncher.IFMLCallHook;
import cpw.mods.fml.relauncher.RelaunchClassLoader;
public class FMLSanityChecker implements IFMLCallHook public class FMLSanityChecker implements IFMLCallHook
{ {
@ -71,7 +72,7 @@ public class FMLSanityChecker implements IFMLCallHook
} }
} }
private RelaunchClassLoader cl; private LaunchClassLoader cl;
@Override @Override
public Void call() throws Exception public Void call() throws Exception
@ -140,12 +141,11 @@ public class FMLSanityChecker implements IFMLCallHook
@Override @Override
public void injectData(Map<String, Object> data) public void injectData(Map<String, Object> data)
{ {
cl = (RelaunchClassLoader) data.get("classLoader"); cl = (LaunchClassLoader) data.get("classLoader");
File mcDir = (File)data.get("mcLocation"); File mcDir = (File)data.get("mcLocation");
FMLDeobfuscatingRemapper.INSTANCE.setup(mcDir, cl, (String) data.get("deobfuscationFileName")); FMLDeobfuscatingRemapper.INSTANCE.setup(mcDir, cl, (String) data.get("deobfuscationFileName"));
File binpatches = new File(mcDir,"binpatch"); File binpatches = new File(mcDir,"binpatch");
File side = new File(binpatches,FMLRelauncher.side().toLowerCase(Locale.ENGLISH)); ClassPatchManager.INSTANCE.setup(FMLLaunchHandler.side(), getClass().getProtectionDomain().getCodeSource());
ClassPatchManager.INSTANCE.setup(side);
} }
} }

View file

@ -5,7 +5,7 @@
* are made available under the terms of the GNU Lesser Public License v2.1 * are made available under the terms of the GNU Lesser Public License v2.1
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* *
* Contributors: * Contributors:
* cpw - implementation * cpw - implementation
*/ */
@ -23,13 +23,13 @@ import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.FieldNode; import org.objectweb.asm.tree.FieldNode;
import org.objectweb.asm.tree.MethodNode; 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.IClassTransformer;
import cpw.mods.fml.relauncher.SideOnly; import cpw.mods.fml.relauncher.SideOnly;
public class SideTransformer implements IClassTransformer public class SideTransformer implements IClassTransformer
{ {
private static String SIDE = FMLRelauncher.side(); private static String SIDE = FMLLaunchHandler.side().name();
private static final boolean DEBUG = false; private static final boolean DEBUG = false;
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @Override

View file

@ -26,6 +26,8 @@ import java.util.logging.Level;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
import java.util.zip.ZipFile; import java.util.zip.ZipFile;
import net.minecraft.launchwrapper.LaunchClassLoader;
import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassReader;
import org.objectweb.asm.commons.Remapper; 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.common.FMLLog;
import cpw.mods.fml.relauncher.FMLRelaunchLog; import cpw.mods.fml.relauncher.FMLRelaunchLog;
import cpw.mods.fml.relauncher.RelaunchClassLoader;
import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.FieldNode; import org.objectweb.asm.tree.FieldNode;
@ -65,7 +66,7 @@ public class FMLDeobfuscatingRemapper extends Remapper {
private Map<String,Map<String,String>> fieldNameMaps; private Map<String,Map<String,String>> fieldNameMaps;
private Map<String,Map<String,String>> methodNameMaps; private Map<String,Map<String,String>> methodNameMaps;
private RelaunchClassLoader classLoader; private LaunchClassLoader classLoader;
private FMLDeobfuscatingRemapper() private FMLDeobfuscatingRemapper()
{ {
@ -124,7 +125,7 @@ public class FMLDeobfuscatingRemapper extends Remapper {
fieldNameMaps = Maps.newHashMapWithExpectedSize(rawFieldMaps.size()); 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; this.classLoader = classLoader;
try try

View file

@ -27,7 +27,7 @@ import cpw.mods.fml.common.FMLLog;
import cpw.mods.fml.common.LoaderException; import cpw.mods.fml.common.LoaderException;
import cpw.mods.fml.common.ModClassLoader; import cpw.mods.fml.common.ModClassLoader;
import cpw.mods.fml.common.ModContainer; import cpw.mods.fml.common.ModContainer;
import cpw.mods.fml.relauncher.RelaunchLibraryManager; import cpw.mods.fml.relauncher.CoreModManager;
public class ModDiscoverer public class ModDiscoverer
{ {
@ -41,7 +41,7 @@ public class ModDiscoverer
public void findClasspathMods(ModClassLoader modClassLoader) public void findClasspathMods(ModClassLoader modClassLoader)
{ {
List<String> knownLibraries = ImmutableList.<String>builder().addAll(modClassLoader.getDefaultLibraries()).addAll(RelaunchLibraryManager.getLibraries()).build(); List<String> knownLibraries = ImmutableList.<String>builder().addAll(modClassLoader.getDefaultLibraries()).addAll(CoreModManager.getLibraries()).build();
File[] minecraftSources = modClassLoader.getParentSources(); File[] minecraftSources = modClassLoader.getParentSources();
if (minecraftSources.length == 1 && minecraftSources[0].isFile()) if (minecraftSources.length == 1 && minecraftSources[0].isFile())
{ {

View file

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

View file

@ -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<String> args;
private File gameDir;
private File assetsDir;
private String profile;
@Override
public void acceptOptions(List<String> 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;
}
}

View file

@ -3,9 +3,19 @@ package cpw.mods.fml.common.patcher;
import java.io.File; import java.io.File;
import java.io.FilenameFilter; import java.io.FilenameFilter;
import java.io.IOException; import java.io.IOException;
import java.net.URISyntaxException;
import java.security.CodeSource;
import java.util.Collections;
import java.util.List; 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.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.ArrayListMultimap;
import com.google.common.collect.ListMultimap; import com.google.common.collect.ListMultimap;
import com.google.common.io.ByteArrayDataInput; import com.google.common.io.ByteArrayDataInput;
@ -13,6 +23,8 @@ import com.google.common.io.ByteStreams;
import com.google.common.io.Files; import com.google.common.io.Files;
import cpw.mods.fml.common.FMLLog; 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; import cpw.mods.fml.repackage.com.nothome.delta.GDiffPatcher;
public class ClassPatchManager { public class ClassPatchManager {
@ -67,48 +79,59 @@ public class ClassPatchManager {
return inputData; 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 File fmlJarFile = new File(fmlLib.getLocation().toURI());
public boolean accept(File dir, String name) fmlJar = new JarFile(fmlJarFile);
{
return Files.getFileExtension(new File(dir,name).getPath()).equals("binpatch");
}
});
if (patchFiles == null)
{
return;
} }
catch (Exception e)
{
FMLRelaunchLog.log(Level.SEVERE, e, "Error occurred reading binary patches. Problems may occur");
throw Throwables.propagate(e);
}
patches = ArrayListMultimap.create(); patches = ArrayListMultimap.create();
for (File patch : patchFiles)
for (JarEntry entry : Collections.list(fmlJar.entries()))
{ {
FMLLog.finest("Reading patch data from %s", patch.getAbsolutePath()); if (binpatchMatcher.matcher(entry.getName()).matches())
ByteArrayDataInput input;
try
{ {
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()); private ClassPatch readPatch(JarEntry patchEntry, JarFile jarFile)
FMLLog.fine("Patch list : %s", patches); {
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);
} }
} }

View file

@ -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;
}

View file

@ -37,11 +37,13 @@ import java.util.jar.Attributes;
import java.util.jar.JarFile; import java.util.jar.JarFile;
import java.util.logging.Level; import java.util.logging.Level;
import net.minecraft.launchwrapper.LaunchClassLoader;
import cpw.mods.fml.common.CertificateHelper; import cpw.mods.fml.common.CertificateHelper;
import cpw.mods.fml.relauncher.IFMLLoadingPlugin.MCVersion; import cpw.mods.fml.relauncher.IFMLLoadingPlugin.MCVersion;
import cpw.mods.fml.relauncher.IFMLLoadingPlugin.TransformerExclusions; 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 String[] rootPlugins = { "cpw.mods.fml.relauncher.FMLCorePlugin" , "net.minecraftforge.classloading.FMLForgePlugin" };
private static List<String> loadedLibraries = new ArrayList<String>(); private static List<String> loadedLibraries = new ArrayList<String>();
@ -50,12 +52,12 @@ public class RelaunchLibraryManager
private static List<ILibrarySet> libraries; private static List<ILibrarySet> libraries;
private static boolean deobfuscatedEnvironment; private static boolean deobfuscatedEnvironment;
public static void handleLaunch(File mcDir, RelaunchClassLoader actualClassLoader) public static void handleLaunch(File mcDir, LaunchClassLoader classLoader)
{ {
try try
{ {
// Are we in a 'decompiled' environment? // 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) if (bs != null)
{ {
FMLRelaunchLog.info("Managed to load a deobfuscated Minecraft name- we are in a deobfuscated environment. Skipping runtime deobfuscation"); 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<IFMLLoadingPlugin, File>(); pluginLocations = new HashMap<IFMLLoadingPlugin, File>();
loadPlugins = new ArrayList<IFMLLoadingPlugin>(); loadPlugins = new ArrayList<IFMLLoadingPlugin>();
libraries = new ArrayList<ILibrarySet>();
for (String s : rootPlugins) for (String s : rootPlugins)
{ {
try try
{ {
IFMLLoadingPlugin plugin = (IFMLLoadingPlugin) Class.forName(s, true, actualClassLoader).newInstance(); IFMLLoadingPlugin plugin = (IFMLLoadingPlugin) Class.forName(s, true, classLoader).newInstance();
loadPlugins.add(plugin); loadPlugins.add(plugin);
for (String libName : plugin.getLibraryRequestClass())
{
libraries.add((ILibrarySet) Class.forName(libName, true, actualClassLoader).newInstance());
}
} }
catch (Exception e) catch (Exception e)
{ {
@ -107,14 +104,14 @@ public class RelaunchLibraryManager
FMLRelaunchLog.info("Found a command line coremod : %s", s); FMLRelaunchLog.info("Found a command line coremod : %s", s);
try try
{ {
actualClassLoader.addTransformerExclusion(s); classLoader.addTransformerExclusion(s);
Class<?> coreModClass = Class.forName(s, true, actualClassLoader); Class<?> coreModClass = Class.forName(s, true, classLoader);
TransformerExclusions trExclusions = coreModClass.getAnnotation(IFMLLoadingPlugin.TransformerExclusions.class); TransformerExclusions trExclusions = coreModClass.getAnnotation(IFMLLoadingPlugin.TransformerExclusions.class);
if (trExclusions!=null) if (trExclusions!=null)
{ {
for (String st : trExclusions.value()) for (String st : trExclusions.value())
{ {
actualClassLoader.addTransformerExclusion(st); classLoader.addTransformerExclusion(st);
} }
} }
IFMLLoadingPlugin plugin = (IFMLLoadingPlugin) coreModClass.newInstance(); IFMLLoadingPlugin plugin = (IFMLLoadingPlugin) coreModClass.newInstance();
@ -123,7 +120,7 @@ public class RelaunchLibraryManager
{ {
for (String libName : plugin.getLibraryRequestClass()) 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); throw new RuntimeException(e);
} }
} }
discoverCoreMods(mcDir, actualClassLoader, loadPlugins, libraries); discoverCoreMods(mcDir, classLoader, loadPlugins, libraries);
List<Throwable> caughtErrors = new ArrayList<Throwable>(); List<Throwable> caughtErrors = new ArrayList<Throwable>();
try try
@ -213,7 +210,7 @@ public class RelaunchLibraryManager
try try
{ {
actualClassLoader.addURL(libFile.toURI().toURL()); classLoader.addURL(libFile.toURI().toURL());
loadedLibraries.add(libName); loadedLibraries.add(libName);
} }
catch (MalformedURLException e) catch (MalformedURLException e)
@ -268,14 +265,14 @@ public class RelaunchLibraryManager
{ {
for (String xformClass : plug.getASMTransformerClass()) for (String xformClass : plug.getASMTransformerClass())
{ {
actualClassLoader.registerTransformer(xformClass); classLoader.registerTransformer(xformClass);
} }
} }
} }
// Deobfuscation transformer, always last // Deobfuscation transformer, always last
if (!deobfuscatedEnvironment) 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"); downloadMonitor.updateProgressString("Running coremod plugins");
Map<String,Object> data = new HashMap<String,Object>(); Map<String,Object> data = new HashMap<String,Object>();
@ -292,10 +289,10 @@ public class RelaunchLibraryManager
{ {
try try
{ {
IFMLCallHook call = (IFMLCallHook) Class.forName(setupClass, true, actualClassLoader).newInstance(); IFMLCallHook call = (IFMLCallHook) Class.forName(setupClass, true, classLoader).newInstance();
Map<String,Object> callData = new HashMap<String, Object>(); Map<String,Object> callData = new HashMap<String, Object>();
callData.put("mcLocation", mcDir); callData.put("mcLocation", mcDir);
callData.put("classLoader", actualClassLoader); callData.put("classLoader", classLoader);
callData.put("coremodLocation", pluginLocations.get(plugin)); callData.put("coremodLocation", pluginLocations.get(plugin));
callData.put("deobfuscationFileName", FMLInjectionData.debfuscationDataName()); callData.put("deobfuscationFileName", FMLInjectionData.debfuscationDataName());
call.injectData(callData); call.injectData(callData);
@ -317,7 +314,7 @@ public class RelaunchLibraryManager
try try
{ {
downloadMonitor.updateProgressString("Validating minecraft"); 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); Method m = loaderClazz.getMethod("injectData", Object[].class);
m.invoke(null, (Object)FMLInjectionData.data()); m.invoke(null, (Object)FMLInjectionData.data());
m = loaderClazz.getMethod("instance"); m = loaderClazz.getMethod("instance");
@ -333,7 +330,7 @@ public class RelaunchLibraryManager
} }
} }
private static void discoverCoreMods(File mcDir, RelaunchClassLoader classLoader, List<IFMLLoadingPlugin> loadPlugins, List<ILibrarySet> libraries) private static void discoverCoreMods(File mcDir, LaunchClassLoader classLoader, List<IFMLLoadingPlugin> loadPlugins, List<ILibrarySet> libraries)
{ {
downloadMonitor.updateProgressString("Discovering coremods"); downloadMonitor.updateProgressString("Discovering coremods");
File coreMods = setupCoreModDir(mcDir); File coreMods = setupCoreModDir(mcDir);

View file

@ -5,7 +5,7 @@
* are made available under the terms of the GNU Lesser Public License v2.1 * are made available under the terms of the GNU Lesser Public License v2.1
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* *
* Contributors: * Contributors:
* cpw - implementation * cpw - implementation
*/ */
@ -20,6 +20,8 @@ import java.util.List;
import java.util.Properties; import java.util.Properties;
import java.util.logging.Level; import java.util.logging.Level;
import net.minecraft.launchwrapper.LaunchClassLoader;
public class FMLInjectionData public class FMLInjectionData
{ {
static File minecraftHome; static File minecraftHome;
@ -33,7 +35,7 @@ public class FMLInjectionData
public static List<String> containers = new ArrayList<String>(); public static List<String> containers = new ArrayList<String>();
static void build(File mcHome, RelaunchClassLoader classLoader) static void build(File mcHome, LaunchClassLoader classLoader)
{ {
minecraftHome = mcHome; minecraftHome = mcHome;
InputStream stream = classLoader.getResourceAsStream("fmlversion.properties"); InputStream stream = classLoader.getResourceAsStream("fmlversion.properties");

View file

@ -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;
}
}

View file

@ -148,6 +148,8 @@ public class FMLRelaunchLog
private static FMLLogFormatter formatter; private static FMLLogFormatter formatter;
static String logFileNamePattern;
private FMLRelaunchLog() private FMLRelaunchLog()
{ {
} }
@ -174,7 +176,7 @@ public class FMLRelaunchLog
formatter = new FMLLogFormatter(); formatter = new FMLLogFormatter();
try try
{ {
File logPath = new File(minecraftHome, FMLRelauncher.logFileNamePattern); File logPath = new File(minecraftHome, logFileNamePattern);
fileHandler = new FileHandler(logPath.getPath(), 0, 3) fileHandler = new FileHandler(logPath.getPath(), 0, 3)
{ {
public synchronized void close() throws SecurityException { public synchronized void close() throws SecurityException {

View file

@ -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<? super Object> 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<? super Object> 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<? super Object> setupNewClientHome(File minecraftHome)
{
Class<? super Object> 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<? super Object> 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(
"<html><div align=\"center\"><font size=\"+1\">There was a fatal error starting up minecraft and FML</font></div><br/>"
+ "Minecraft cannot launch in it's current configuration<br/>"
+ "Please consult the file <i><a href=\"file:///%s\">%s</a></i> for further information</html>", 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<? super Object> 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<? super Object> 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<? super Object> 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;
}
}

View file

@ -32,6 +32,7 @@ public interface IFMLLoadingPlugin
* *
* @return a list of classes that implement the ILibrarySet interface * @return a list of classes that implement the ILibrarySet interface
*/ */
@Deprecated
String[] getLibraryRequestClass(); String[] getLibraryRequestClass();
/** /**
* Return a list of classes that implements the IClassTransformer interface * Return a list of classes that implements the IClassTransformer interface

View file

@ -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<URL> sources;
private ClassLoader parent;
private List<IClassTransformer> transformers;
private Map<String, Class> cachedClasses;
private Set<String> invalidClasses;
private Set<String> classLoaderExceptions = new HashSet<String>();
private Set<String> transformerExceptions = new HashSet<String>();
private Map<Package,Manifest> packageManifests = new HashMap<Package,Manifest>();
private IClassNameTransformer renameTransformer;
private static Manifest EMPTY = new Manifest();
private ThreadLocal<byte[]> loadBuffer = new ThreadLocal<byte[]>();
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<URL>(Arrays.asList(sources));
this.parent = getClass().getClassLoader();
this.cachedClasses = new HashMap<String,Class>(1000);
this.invalidClasses = new HashSet<String>(1000);
this.transformers = new ArrayList<IClassTransformer>(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<URL> 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<IClassTransformer> 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
}
}
}
}
}

View file

@ -4,6 +4,9 @@ import java.io.File;
import java.net.URLClassLoader; import java.net.URLClassLoader;
import java.util.logging.Level; import java.util.logging.Level;
import net.minecraft.launchwrapper.Launch;
import net.minecraft.launchwrapper.LaunchClassLoader;
import com.google.common.base.Throwables; import com.google.common.base.Throwables;
public class ServerLaunchWrapper { public class ServerLaunchWrapper {
@ -23,42 +26,7 @@ public class ServerLaunchWrapper {
private void run(String[] args) private void run(String[] args)
{ {
File minecraftHome = new File("."); Launch.main(args);
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<? super Object> 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);
}
} }
} }

View file

@ -5,7 +5,7 @@
* are made available under the terms of the GNU Lesser Public License v2.1 * are made available under the terms of the GNU Lesser Public License v2.1
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* *
* Contributors: * Contributors:
* cpw - implementation * cpw - implementation
*/ */
@ -13,7 +13,7 @@
package cpw.mods.fml.relauncher; package cpw.mods.fml.relauncher;
public enum Side { public enum Side {
CLIENT, SERVER, BUKKIT; CLIENT, SERVER;
/** /**
* @return If this is the server environment * @return If this is the server environment

View file

@ -5,7 +5,7 @@
* are made available under the terms of the GNU Lesser Public License v2.1 * are made available under the terms of the GNU Lesser Public License v2.1
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* *
* Contributors: * Contributors:
* cpw - implementation * cpw - implementation
*/ */
@ -17,7 +17,22 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; 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 <em>only</em> apply to the direct element marked. This code:
* <code> @SideOnly public MyField field = new MyField();</code> will <strong>not</strong> 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) @Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.CONSTRUCTOR}) @Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.CONSTRUCTOR})
public @interface SideOnly public @interface SideOnly

View file

@ -1,18 +1,16 @@
--- ../src-base/minecraft/net/minecraft/client/Minecraft.java --- ../src-base/minecraft/net/minecraft/client/Minecraft.java
+++ ../src-work/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; package net.minecraft.client;
+import cpw.mods.fml.client.FMLClientHandler; +import cpw.mods.fml.client.FMLClientHandler;
+import cpw.mods.fml.common.FMLCommonHandler; +import cpw.mods.fml.common.FMLCommonHandler;
+import cpw.mods.fml.common.registry.GameData; +import cpw.mods.fml.common.registry.GameData;
+import cpw.mods.fml.common.registry.ItemData; +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.Side;
import cpw.mods.fml.relauncher.SideOnly; import cpw.mods.fml.relauncher.SideOnly;
import java.awt.BorderLayout; import java.awt.BorderLayout;
@@ -115,6 +121,8 @@ @@ -115,6 +119,8 @@
import org.lwjgl.opengl.PixelFormat; import org.lwjgl.opengl.PixelFormat;
import org.lwjgl.util.glu.GLU; import org.lwjgl.util.glu.GLU;
@ -21,7 +19,7 @@
@SideOnly(Side.CLIENT) @SideOnly(Side.CLIENT)
public abstract class Minecraft implements Runnable, IPlayerUsage 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_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); 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) if (this.field_71474_y.field_74363_ab != null)
{ {
StringTranslate.func_74808_a().func_74810_a(this.field_71474_y.field_74363_ab, false); 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); 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); this.field_71452_i = new EffectRenderer(this.field_71441_e, this.field_71446_o);
@ -39,7 +37,7 @@
try try
{ {
this.field_71430_V = new ThreadDownloadResources(this.field_71412_D, this); this.field_71430_V = new ThreadDownloadResources(this.field_71412_D, this);
@@ -362,6 +374,8 @@ @@ -362,6 +372,8 @@
{ {
this.func_71352_k(); this.func_71352_k();
} }
@ -48,7 +46,7 @@
} }
private void func_71357_I() throws LWJGLException private void func_71357_I() throws LWJGLException
@@ -723,9 +737,11 @@ @@ -723,9 +735,11 @@
if (!this.field_71454_w) if (!this.field_71454_w)
{ {
@ -60,7 +58,7 @@
} }
GL11.glFlush(); GL11.glFlush();
@@ -1255,10 +1271,14 @@ @@ -1255,10 +1269,14 @@
public void func_71407_l() public void func_71407_l()
{ {
@ -75,7 +73,7 @@
this.field_71424_I.func_76320_a("stats"); this.field_71424_I.func_76320_a("stats");
this.field_71413_E.func_77449_e(); this.field_71413_E.func_77449_e();
@@ -1716,6 +1736,8 @@ @@ -1716,6 +1734,8 @@
this.field_71453_ak.func_74428_b(); this.field_71453_ak.func_74428_b();
} }
@ -84,7 +82,7 @@
this.field_71424_I.func_76319_b(); this.field_71424_I.func_76319_b();
this.field_71423_H = func_71386_F(); 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); this.field_71413_E.func_77450_a(StatList.field_75936_f, 1);
@ -112,16 +110,3 @@
this.field_71455_al = true; this.field_71455_al = true;
this.field_71461_s.func_73720_a(StatCollector.func_74838_a("menu.loadingLevel")); 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;

View file

@ -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;

View file

@ -1,15 +1,13 @@
--- ../src-base/minecraft/net/minecraft/server/MinecraftServer.java --- ../src-base/minecraft/net/minecraft/server/MinecraftServer.java
+++ ../src-work/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; package net.minecraft.server;
+import cpw.mods.fml.common.FMLCommonHandler; +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.Side;
import cpw.mods.fml.relauncher.SideOnly; import cpw.mods.fml.relauncher.SideOnly;
import java.awt.GraphicsEnvironment; import java.awt.GraphicsEnvironment;
@@ -352,7 +355,11 @@ @@ -352,7 +353,11 @@
{ {
if (this.func_71197_b()) if (this.func_71197_b())
{ {
@ -21,7 +19,7 @@
for (long j = 0L; this.field_71317_u; this.field_71296_Q = true) for (long j = 0L; this.field_71317_u; this.field_71296_Q = true)
{ {
@@ -391,6 +398,7 @@ @@ -391,6 +396,7 @@
Thread.sleep(1L); Thread.sleep(1L);
} }
@ -29,7 +27,7 @@
} }
else else
{ {
@@ -399,6 +407,10 @@ @@ -399,6 +405,10 @@
} }
catch (Throwable throwable) catch (Throwable throwable)
{ {
@ -40,7 +38,7 @@
throwable.printStackTrace(); throwable.printStackTrace();
this.func_98033_al().func_98234_c("Encountered an unexpected exception " + throwable.getClass().getSimpleName(), throwable); this.func_98033_al().func_98234_c("Encountered an unexpected exception " + throwable.getClass().getSimpleName(), throwable);
CrashReport crashreport = null; CrashReport crashreport = null;
@@ -429,6 +441,10 @@ @@ -429,6 +439,10 @@
{ {
try try
{ {
@ -51,7 +49,7 @@
this.func_71260_j(); this.func_71260_j();
this.field_71316_v = true; this.field_71316_v = true;
} }
@@ -438,6 +454,8 @@ @@ -438,6 +452,8 @@
} }
finally finally
{ {
@ -60,7 +58,7 @@
this.func_71240_o(); this.func_71240_o();
} }
} }
@@ -454,8 +472,10 @@ @@ -454,8 +470,10 @@
public void func_71217_p() public void func_71217_p()
{ {
@ -71,7 +69,7 @@
++this.field_71315_w; ++this.field_71315_w;
if (this.field_71295_T) 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();
this.field_71304_b.func_76319_b(); this.field_71304_b.func_76319_b();
@ -79,7 +77,7 @@
} }
public void func_71190_q() public void func_71190_q()
@@ -528,6 +549,7 @@ @@ -528,6 +547,7 @@
} }
this.field_71304_b.func_76320_a("tick"); this.field_71304_b.func_76320_a("tick");
@ -87,7 +85,7 @@
CrashReport crashreport; CrashReport crashreport;
try try
@@ -552,6 +574,7 @@ @@ -552,6 +572,7 @@
throw new ReportedException(crashreport); throw new ReportedException(crashreport);
} }
@ -95,7 +93,7 @@
this.field_71304_b.func_76319_b(); this.field_71304_b.func_76319_b();
this.field_71304_b.func_76320_a("tracker"); this.field_71304_b.func_76320_a("tracker");
worldserver.func_73039_n().func_72788_a(); worldserver.func_73039_n().func_72788_a();
@@ -679,7 +702,7 @@ @@ -679,7 +700,7 @@
public String getServerModName() public String getServerModName()
{ {
@ -104,17 +102,3 @@
} }
public CrashReport func_71230_b(CrashReport p_71230_1_) 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;