Merge in binpatch and use launcher
This commit is contained in:
parent
21240df8bc
commit
07a5efe612
23 changed files with 414 additions and 1103 deletions
129
fml/build.xml
129
fml/build.xml
|
@ -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,10 +34,10 @@
|
||||||
<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>
|
||||||
<condition property="signature.exists">
|
<condition property="signature.exists">
|
||||||
<available file="${env.JENKINS_HOME}/fmlsigned.properties"/>
|
<available file="${env.JENKINS_HOME}/fmlsigned.properties" />
|
||||||
</condition>
|
</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" />
|
||||||
|
@ -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">
|
||||||
|
@ -92,16 +92,16 @@
|
||||||
<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>
|
||||||
|
|
||||||
|
@ -112,7 +112,7 @@
|
||||||
<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>
|
||||||
|
@ -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>
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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())
|
||||||
{
|
{
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
49
fml/common/cpw/mods/fml/common/launcher/FMLTweaker.java
Normal file
49
fml/common/cpw/mods/fml/common/launcher/FMLTweaker.java
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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,34 +79,50 @@ 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");
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
FMLRelaunchLog.log(Level.SEVERE, e, "Error occurred reading binary patches. Problems may occur");
|
||||||
|
throw Throwables.propagate(e);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
if (patchFiles == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
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())
|
||||||
|
{
|
||||||
|
ClassPatch cp = readPatch(entry, fmlJar);
|
||||||
|
if (cp != null)
|
||||||
|
{
|
||||||
|
patches.put(cp.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()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private ClassPatch readPatch(JarEntry patchEntry, JarFile jarFile)
|
||||||
|
{
|
||||||
|
FMLLog.finest("Reading patch data from %s in file %s", patchEntry.getName(), jarFile.getName());
|
||||||
ByteArrayDataInput input;
|
ByteArrayDataInput input;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
input = ByteStreams.newDataInput(Files.toByteArray(patch));
|
input = ByteStreams.newDataInput(ByteStreams.toByteArray(jarFile.getInputStream(patchEntry)));
|
||||||
}
|
}
|
||||||
catch (IOException e)
|
catch (IOException e)
|
||||||
{
|
{
|
||||||
FMLLog.log(Level.WARNING, e, "Unable to read binpatch file %s - ignoring", patch.getAbsolutePath());
|
FMLLog.log(Level.WARNING, e, "Unable to read binpatch file %s - ignoring", patchEntry.getName());
|
||||||
continue;
|
return null;
|
||||||
}
|
}
|
||||||
String name = input.readUTF();
|
String name = input.readUTF();
|
||||||
String sourceClassName = input.readUTF();
|
String sourceClassName = input.readUTF();
|
||||||
|
@ -104,11 +132,6 @@ public class ClassPatchManager {
|
||||||
byte[] patchBytes = new byte[patchLength];
|
byte[] patchBytes = new byte[patchLength];
|
||||||
input.readFully(patchBytes);
|
input.readFully(patchBytes);
|
||||||
|
|
||||||
ClassPatch cp = new ClassPatch(name, sourceClassName, targetClassName, exists, patchBytes);
|
return new ClassPatch(name, sourceClassName, targetClassName, exists, patchBytes);
|
||||||
patches.put(sourceClassName, cp);
|
|
||||||
}
|
|
||||||
|
|
||||||
FMLLog.fine("Read %d binary patches from %s", patches.size(), dirToScan.getAbsolutePath());
|
|
||||||
FMLLog.fine("Patch list : %s", patches);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -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);
|
|
@ -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");
|
||||||
|
|
116
fml/common/cpw/mods/fml/relauncher/FMLLaunchHandler.java
Normal file
116
fml/common/cpw/mods/fml/relauncher/FMLLaunchHandler.java
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 {
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
|
||||||
|
|
|
@ -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;
|
|
|
@ -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;
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue