2012-03-30 10:11:13 -04:00
/*
2012-04-02 18:09:06 -04:00
* The FML Forge Mod Loader suite. Copyright (C) 2012 cpw
2012-04-05 10:07:52 -04:00
*
2012-03-30 10:11:13 -04:00
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or any later version.
2012-04-05 10:07:52 -04:00
*
2012-03-30 10:11:13 -04:00
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
2012-04-05 10:07:52 -04:00
*
2012-03-30 10:11:13 -04:00
* You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
2012-04-02 18:09:06 -04:00
package cpw.mods.fml.common ;
2012-03-30 10:11:13 -04:00
2012-04-18 14:03:30 -04:00
import java.io.File ;
2012-09-16 21:05:11 -04:00
import java.io.FileInputStream ;
2012-07-23 16:33:17 -02:30
import java.lang.annotation.Annotation ;
import java.lang.reflect.Field ;
import java.lang.reflect.Method ;
2012-08-26 10:45:00 -04:00
import java.lang.reflect.Modifier ;
2012-12-17 14:30:51 -05:00
import java.security.cert.Certificate ;
2012-07-30 00:33:21 -04:00
import java.util.Arrays ;
2012-04-02 23:06:30 -04:00
import java.util.List ;
2012-05-11 17:31:28 -04:00
import java.util.Map ;
2012-09-16 21:05:11 -04:00
import java.util.Properties ;
2012-08-23 13:43:25 -04:00
import java.util.Set ;
2013-12-16 11:47:48 -05:00
import org.apache.logging.log4j.Level ;
2012-09-16 21:05:11 -04:00
import java.util.zip.ZipEntry ;
import java.util.zip.ZipFile ;
2012-04-02 23:06:30 -04:00
2012-08-26 10:45:00 -04:00
import com.google.common.base.Function ;
2012-08-14 13:36:29 -04:00
import com.google.common.base.Strings ;
2012-07-22 11:56:38 -02:30
import com.google.common.base.Throwables ;
2012-07-23 16:33:17 -02:30
import com.google.common.collect.ArrayListMultimap ;
2012-12-17 19:55:46 -05:00
import com.google.common.collect.ImmutableList ;
import com.google.common.collect.ImmutableList.Builder ;
2013-06-27 08:38:11 -04:00
import com.google.common.collect.ImmutableMap ;
2012-12-17 14:30:51 -05:00
import com.google.common.collect.ImmutableSet ;
2013-06-26 14:52:56 -04:00
import com.google.common.collect.ListMultimap ;
2012-07-22 11:56:38 -02:30
import com.google.common.collect.Lists ;
2013-09-27 10:45:20 -04:00
import com.google.common.collect.Maps ;
2012-08-26 10:45:00 -04:00
import com.google.common.collect.SetMultimap ;
2012-08-23 13:43:25 -04:00
import com.google.common.collect.Sets ;
2012-07-22 11:56:38 -02:30
import com.google.common.eventbus.EventBus ;
import com.google.common.eventbus.Subscribe ;
2012-07-23 16:33:17 -02:30
import cpw.mods.fml.common.Mod.Instance ;
import cpw.mods.fml.common.Mod.Metadata ;
2012-08-06 09:52:42 -04:00
import cpw.mods.fml.common.discovery.ASMDataTable ;
2012-08-26 10:45:00 -04:00
import cpw.mods.fml.common.discovery.ASMDataTable.ASMData ;
2013-09-25 11:46:11 -04:00
import cpw.mods.fml.common.discovery.ModCandidate ;
2012-07-22 11:56:38 -02:30
import cpw.mods.fml.common.event.FMLConstructionEvent ;
2012-10-24 16:39:55 -04:00
import cpw.mods.fml.common.event.FMLEvent ;
2013-11-10 11:49:06 -05:00
import cpw.mods.fml.common.event.FMLFingerprintViolationEvent ;
2012-07-23 16:33:17 -02:30
import cpw.mods.fml.common.event.FMLInitializationEvent ;
2012-10-24 16:39:55 -04:00
import cpw.mods.fml.common.event.FMLInterModComms.IMCEvent ;
2012-07-23 16:33:17 -02:30
import cpw.mods.fml.common.event.FMLPostInitializationEvent ;
import cpw.mods.fml.common.event.FMLPreInitializationEvent ;
2013-01-22 09:11:44 -05:00
import cpw.mods.fml.common.event.FMLServerAboutToStartEvent ;
2012-08-02 09:31:03 -02:30
import cpw.mods.fml.common.event.FMLServerStartedEvent ;
import cpw.mods.fml.common.event.FMLServerStartingEvent ;
2012-12-30 23:52:38 -05:00
import cpw.mods.fml.common.event.FMLServerStoppedEvent ;
2012-08-02 09:31:03 -02:30
import cpw.mods.fml.common.event.FMLServerStoppingEvent ;
2013-12-06 14:52:33 -05:00
import cpw.mods.fml.common.network.NetworkRegistry ;
2012-07-30 17:01:27 -04:00
import cpw.mods.fml.common.versioning.ArtifactVersion ;
import cpw.mods.fml.common.versioning.DefaultArtifactVersion ;
2012-10-02 01:29:46 -04:00
import cpw.mods.fml.common.versioning.VersionParser ;
import cpw.mods.fml.common.versioning.VersionRange ;
2012-07-22 11:56:38 -02:30
2012-04-05 10:07:52 -04:00
public class FMLModContainer implements ModContainer
{
private Object modInstance ;
2012-04-18 14:03:30 -04:00
private File source ;
2012-05-15 16:19:46 -04:00
private ModMetadata modMetadata ;
2012-07-22 11:56:38 -02:30
private String className ;
private Map < String , Object > descriptor ;
2012-07-23 16:33:17 -02:30
private boolean enabled = true ;
2012-08-26 10:45:00 -04:00
private String internalVersion ;
2012-07-22 11:56:38 -02:30
private boolean overridesMetadata ;
private EventBus eventBus ;
private LoadController controller ;
2012-07-30 17:01:27 -04:00
private DefaultArtifactVersion processedVersion ;
2012-08-06 09:52:42 -04:00
private boolean isNetworkMod ;
2012-04-05 10:07:52 -04:00
2012-08-16 13:55:42 -04:00
private String annotationDependencies ;
2012-10-02 01:29:46 -04:00
private VersionRange minecraftAccepted ;
2012-12-17 14:30:51 -05:00
private boolean fingerprintNotPresent ;
private Set < String > sourceFingerprints ;
2012-12-17 19:55:46 -05:00
private Certificate certificate ;
2013-03-07 20:22:24 -05:00
private String modLanguage ;
private ILanguageAdapter languageAdapter ;
2013-06-26 14:52:56 -04:00
private ListMultimap < Class <? extends FMLEvent > , Method > eventMethods ;
2013-06-27 08:38:11 -04:00
private Map < String , String > customModProperties ;
2013-09-25 11:46:11 -04:00
private ModCandidate candidate ;
2013-11-10 11:58:34 -05:00
private static final Set < Class <? extends FMLEvent >> modEventTypes = ImmutableSet . < Class <? extends FMLEvent >> builder ()
. add ( FMLPreInitializationEvent . class )
. add ( FMLInitializationEvent . class )
. add ( FMLPostInitializationEvent . class )
. add ( FMLServerAboutToStartEvent . class )
. add ( FMLServerStartingEvent . class )
. add ( FMLServerStartedEvent . class )
. add ( FMLServerStoppingEvent . class )
. add ( FMLServerStoppedEvent . class )
. add ( IMCEvent . class )
. add ( FMLFingerprintViolationEvent . class )
. build ();
2012-08-04 11:26:51 -04:00
2013-09-25 11:46:11 -04:00
public FMLModContainer ( String className , ModCandidate container , Map < String , Object > modDescriptor )
2012-04-05 10:07:52 -04:00
{
2012-07-22 11:56:38 -02:30
this . className = className ;
2013-09-25 11:46:11 -04:00
this . source = container . getModContainer ();
this . candidate = container ;
2012-07-22 11:56:38 -02:30
this . descriptor = modDescriptor ;
2013-03-07 20:22:24 -05:00
this . modLanguage = ( String ) modDescriptor . get ( "modLanguage" );
2013-04-20 23:31:22 -04:00
this . languageAdapter = "scala" . equals ( modLanguage ) ? new ILanguageAdapter . ScalaAdapter () : new ILanguageAdapter . JavaAdapter ();
2013-06-26 14:52:56 -04:00
this . eventMethods = ArrayListMultimap . create ();
2012-04-05 10:07:52 -04:00
}
2013-03-07 20:22:24 -05:00
private ILanguageAdapter getLanguageAdapter ()
{
return languageAdapter ;
}
2012-04-05 10:07:52 -04:00
@Override
2012-07-22 11:56:38 -02:30
public String getModId ()
2012-04-05 10:07:52 -04:00
{
2012-07-22 11:56:38 -02:30
return ( String ) descriptor . get ( "modid" );
2012-04-05 10:07:52 -04:00
}
@Override
public String getName ()
{
2012-07-22 11:56:38 -02:30
return modMetadata . name ;
2012-05-10 09:42:31 -04:00
}
2012-04-05 10:07:52 -04:00
@Override
2012-07-22 11:56:38 -02:30
public String getVersion ()
2012-04-05 10:07:52 -04:00
{
2012-08-26 10:45:00 -04:00
return internalVersion ;
2012-04-05 10:07:52 -04:00
}
@Override
2012-04-18 14:03:30 -04:00
public File getSource ()
2012-04-05 10:07:52 -04:00
{
return source ;
}
@Override
2012-07-22 11:56:38 -02:30
public ModMetadata getMetadata ()
2012-04-05 10:07:52 -04:00
{
2012-07-22 11:56:38 -02:30
return modMetadata ;
2012-04-05 10:07:52 -04:00
}
@Override
2012-07-22 11:56:38 -02:30
public void bindMetadata ( MetadataCollection mc )
2012-04-05 10:07:52 -04:00
{
2012-07-23 16:33:17 -02:30
modMetadata = mc . getMetadataForId ( getModId (), descriptor );
2012-07-30 00:33:21 -04:00
2012-09-25 18:57:42 -04:00
if ( descriptor . containsKey ( "useMetadata" ))
2012-07-22 11:56:38 -02:30
{
2012-09-25 18:57:42 -04:00
overridesMetadata = ! (( Boolean ) descriptor . get ( "useMetadata" )). booleanValue ();
2012-07-22 11:56:38 -02:30
}
2012-07-30 00:33:21 -04:00
2012-07-22 11:56:38 -02:30
if ( overridesMetadata || ! modMetadata . useDependencyInformation )
{
2012-08-23 13:43:25 -04:00
Set < ArtifactVersion > requirements = Sets . newHashSet ();
2012-07-30 17:01:27 -04:00
List < ArtifactVersion > dependencies = Lists . newArrayList ();
List < ArtifactVersion > dependants = Lists . newArrayList ();
2012-08-16 13:55:42 -04:00
annotationDependencies = ( String ) descriptor . get ( "dependencies" );
Loader . instance (). computeDependencies ( annotationDependencies , requirements , dependencies , dependants );
2012-07-22 11:56:38 -02:30
modMetadata . requiredMods = requirements ;
modMetadata . dependencies = dependencies ;
modMetadata . dependants = dependants ;
2013-12-16 11:47:48 -05:00
FMLLog . log ( getModId (), Level . TRACE , "Parsed dependency info : %s %s %s" , requirements , dependencies , dependants );
2012-07-22 11:56:38 -02:30
}
2012-08-23 16:46:23 -04:00
else
{
2013-12-16 11:47:48 -05:00
FMLLog . log ( getModId (), Level . TRACE , "Using mcmod dependency info : %s %s %s" , modMetadata . requiredMods , modMetadata . dependencies , modMetadata . dependants );
2012-08-23 16:46:23 -04:00
}
2012-08-14 13:36:29 -04:00
if ( Strings . isNullOrEmpty ( modMetadata . name ))
{
2013-01-30 18:57:21 -05:00
FMLLog . log ( getModId (), Level . INFO , "Mod %s is missing the required element 'name'. Substituting %s" , getModId (), getModId ());
2012-08-14 13:36:29 -04:00
modMetadata . name = getModId ();
}
2012-08-26 10:45:00 -04:00
internalVersion = ( String ) descriptor . get ( "version" );
2012-09-21 17:39:52 -04:00
if ( Strings . isNullOrEmpty ( internalVersion ))
2012-09-16 21:05:11 -04:00
{
2012-09-16 21:42:59 -04:00
Properties versionProps = searchForVersionProperties ();
if ( versionProps != null )
{
internalVersion = versionProps . getProperty ( getModId () + ".version" );
2013-12-16 11:47:48 -05:00
FMLLog . log ( getModId (), Level . DEBUG , "Found version %s for mod %s in version.properties, using" , internalVersion , getModId ());
2012-09-16 21:42:59 -04:00
}
2012-09-16 21:05:11 -04:00
}
2012-08-26 10:45:00 -04:00
if ( Strings . isNullOrEmpty ( internalVersion ) && ! Strings . isNullOrEmpty ( modMetadata . version ))
{
2013-12-16 11:47:48 -05:00
FMLLog . log ( getModId (), Level . WARN , "Mod %s is missing the required element 'version' and a version.properties file could not be found. Falling back to metadata version %s" , getModId (), modMetadata . version );
2012-09-16 20:56:19 -04:00
internalVersion = modMetadata . version ;
2012-08-26 10:45:00 -04:00
}
if ( Strings . isNullOrEmpty ( internalVersion ))
2012-08-23 13:43:25 -04:00
{
2013-12-16 11:47:48 -05:00
FMLLog . log ( getModId (), Level . WARN , "Mod %s is missing the required element 'version' and no fallback can be found. Substituting '1.0'." , getModId ());
2012-08-26 10:45:00 -04:00
modMetadata . version = internalVersion = "1.0" ;
2012-08-23 13:43:25 -04:00
}
2012-10-02 01:29:46 -04:00
String mcVersionString = ( String ) descriptor . get ( "acceptedMinecraftVersions" );
if ( ! Strings . isNullOrEmpty ( mcVersionString ))
{
minecraftAccepted = VersionParser . parseRange ( mcVersionString );
}
else
{
minecraftAccepted = Loader . instance (). getMinecraftModContainer (). getStaticVersionRange ();
}
2012-04-05 10:07:52 -04:00
}
2012-09-16 21:42:59 -04:00
public Properties searchForVersionProperties ()
2012-09-16 21:05:11 -04:00
{
try
{
2013-12-16 11:47:48 -05:00
FMLLog . log ( getModId (), Level . DEBUG , "Attempting to load the file version.properties from %s to locate a version number for %s" , getSource (). getName (), getModId ());
2012-09-16 21:42:59 -04:00
Properties version = null ;
if ( getSource (). isFile ())
{
ZipFile source = new ZipFile ( getSource ());
ZipEntry versionFile = source . getEntry ( "version.properties" );
if ( versionFile != null )
{
version = new Properties ();
version . load ( source . getInputStream ( versionFile ));
}
source . close ();
}
else if ( getSource (). isDirectory ())
2012-09-16 21:05:11 -04:00
{
2012-09-16 21:42:59 -04:00
File propsFile = new File ( getSource (), "version.properties" );
if ( propsFile . exists () && propsFile . isFile ())
{
version = new Properties ();
FileInputStream fis = new FileInputStream ( propsFile );
version . load ( fis );
fis . close ();
}
2012-09-16 21:05:11 -04:00
}
return version ;
}
catch ( Exception e )
{
Throwables . propagateIfPossible ( e );
2013-12-16 11:47:48 -05:00
FMLLog . log ( getModId (), Level . TRACE , "Failed to find a usable version.properties file" );
2012-09-16 21:05:11 -04:00
return null ;
}
}
2012-04-05 10:07:52 -04:00
@Override
2012-07-22 11:56:38 -02:30
public void setEnabledState ( boolean enabled )
2012-04-05 10:07:52 -04:00
{
2012-07-22 11:56:38 -02:30
this . enabled = enabled ;
2012-04-05 10:07:52 -04:00
}
@Override
2012-08-23 13:43:25 -04:00
public Set < ArtifactVersion > getRequirements ()
2012-04-05 10:07:52 -04:00
{
2012-07-22 11:56:38 -02:30
return modMetadata . requiredMods ;
2012-04-05 10:07:52 -04:00
}
@Override
2012-07-30 17:01:27 -04:00
public List < ArtifactVersion > getDependencies ()
2012-04-05 10:07:52 -04:00
{
2012-07-22 11:56:38 -02:30
return modMetadata . dependencies ;
2012-04-05 10:07:52 -04:00
}
@Override
2012-07-30 17:01:27 -04:00
public List < ArtifactVersion > getDependants ()
2012-04-05 10:07:52 -04:00
{
2012-07-22 11:56:38 -02:30
return modMetadata . dependants ;
2012-04-05 10:07:52 -04:00
}
@Override
2012-07-22 11:56:38 -02:30
public String getSortingRules ()
2012-04-05 10:07:52 -04:00
{
2012-08-23 14:28:49 -04:00
return (( overridesMetadata || ! modMetadata . useDependencyInformation ) ? Strings . nullToEmpty ( annotationDependencies ) : modMetadata . printableSortingRules ());
2012-04-05 10:07:52 -04:00
}
@Override
2012-07-22 11:56:38 -02:30
public boolean matches ( Object mod )
2012-04-05 10:07:52 -04:00
{
2012-07-22 11:56:38 -02:30
return mod == modInstance ;
2012-04-05 10:07:52 -04:00
}
2012-04-08 02:00:57 -04:00
@Override
2012-07-22 11:56:38 -02:30
public Object getMod ()
2012-04-08 02:00:57 -04:00
{
2012-07-22 11:56:38 -02:30
return modInstance ;
2012-04-08 02:00:57 -04:00
}
2012-04-09 10:18:24 -04:00
2012-06-02 15:13:55 -04:00
@Override
2012-07-22 11:56:38 -02:30
public boolean registerBus ( EventBus bus , LoadController controller )
2012-06-02 15:13:55 -04:00
{
2012-07-22 11:56:38 -02:30
if ( this . enabled )
{
2013-12-16 11:47:48 -05:00
FMLLog . log ( getModId (), Level . DEBUG , "Enabling mod %s" , getModId ());
2012-07-22 11:56:38 -02:30
this . eventBus = bus ;
this . controller = controller ;
eventBus . register ( this );
return true ;
}
else
{
return false ;
}
2012-06-02 15:13:55 -04:00
}
2012-07-30 00:33:21 -04:00
2013-11-10 11:49:06 -05:00
@SuppressWarnings ( "unchecked" )
2013-06-26 14:52:56 -04:00
private Method gatherAnnotations ( Class <?> clazz ) throws Exception
2012-07-23 16:33:17 -02:30
{
2013-06-26 14:52:56 -04:00
Method factoryMethod = null ;
2012-07-23 16:33:17 -02:30
for ( Method m : clazz . getDeclaredMethods ())
{
for ( Annotation a : m . getAnnotations ())
{
2013-11-10 11:58:34 -05:00
if ( a . annotationType (). equals ( Mod . EventHandler . class ))
2013-06-26 14:52:56 -04:00
{
2013-11-10 11:58:34 -05:00
if ( m . getParameterTypes (). length == 1 && modEventTypes . contains ( m . getParameterTypes () [ 0 ] ))
2013-06-26 14:52:56 -04:00
{
m . setAccessible ( true );
2013-07-02 01:08:51 -04:00
eventMethods . put (( Class <? extends FMLEvent > ) m . getParameterTypes () [ 0 ] , m );
2013-06-26 14:52:56 -04:00
}
else
{
2013-12-16 11:47:48 -05:00
FMLLog . log ( getModId (), Level . ERROR , "The mod %s appears to have an invalid event annotation %s. This annotation can only apply to methods with recognized event arguments - it will not be called" , getModId (), a . annotationType (). getSimpleName ());
2013-06-26 14:52:56 -04:00
}
}
else if ( a . annotationType (). equals ( Mod . InstanceFactory . class ))
{
if ( Modifier . isStatic ( m . getModifiers ()) && m . getParameterTypes (). length == 0 && factoryMethod == null )
{
m . setAccessible ( true );
factoryMethod = m ;
}
else if ( ! ( Modifier . isStatic ( m . getModifiers ()) && m . getParameterTypes (). length == 0 ))
{
2013-12-16 11:47:48 -05:00
FMLLog . log ( getModId (), Level . ERROR , "The InstanceFactory annotation can only apply to a static method, taking zero arguments - it will be ignored on %s(%s)" , m . getName (), Arrays . asList ( m . getParameterTypes ()));
2013-06-26 14:52:56 -04:00
}
else if ( factoryMethod != null )
{
2013-12-16 11:47:48 -05:00
FMLLog . log ( getModId (), Level . ERROR , "The InstanceFactory annotation can only be used once, the application to %s(%s) will be ignored" , m . getName (), Arrays . asList ( m . getParameterTypes ()));
2013-06-26 14:52:56 -04:00
}
}
2012-07-23 16:33:17 -02:30
}
}
2013-06-26 14:52:56 -04:00
return factoryMethod ;
2012-07-23 16:33:17 -02:30
}
2012-08-26 10:45:00 -04:00
private void processFieldAnnotations ( ASMDataTable asmDataTable ) throws Exception
2012-07-23 16:33:17 -02:30
{
2012-08-26 10:45:00 -04:00
SetMultimap < String , ASMData > annotations = asmDataTable . getAnnotationsFor ( this );
2012-07-30 00:33:21 -04:00
2012-08-26 10:45:00 -04:00
parseSimpleFieldAnnotation ( annotations , Instance . class . getName (), new Function < ModContainer , Object > ()
2012-07-23 16:33:17 -02:30
{
2012-08-26 10:45:00 -04:00
public Object apply ( ModContainer mc )
{
return mc . getMod ();
}
});
parseSimpleFieldAnnotation ( annotations , Metadata . class . getName (), new Function < ModContainer , Object > ()
{
public Object apply ( ModContainer mc )
{
return mc . getMetadata ();
}
});
2012-07-23 16:33:17 -02:30
}
2012-08-26 10:45:00 -04:00
private void parseSimpleFieldAnnotation ( SetMultimap < String , ASMData > annotations , String annotationClassName , Function < ModContainer , Object > retreiver ) throws IllegalAccessException
{
String [] annName = annotationClassName . split ( "\\." );
String annotationName = annName [ annName . length - 1 ] ;
for ( ASMData targets : annotations . get ( annotationClassName ))
{
String targetMod = ( String ) targets . getAnnotationInfo (). get ( "value" );
Field f = null ;
Object injectedMod = null ;
ModContainer mc = this ;
boolean isStatic = false ;
Class <?> clz = modInstance . getClass ();
if ( ! Strings . isNullOrEmpty ( targetMod ))
{
2012-08-26 10:55:55 -04:00
if ( Loader . isModLoaded ( targetMod ))
{
mc = Loader . instance (). getIndexedModList (). get ( targetMod );
}
else
{
mc = null ;
}
2012-08-26 10:45:00 -04:00
}
if ( mc != null )
{
try
{
clz = Class . forName ( targets . getClassName (), true , Loader . instance (). getModClassLoader ());
f = clz . getDeclaredField ( targets . getObjectName ());
f . setAccessible ( true );
isStatic = Modifier . isStatic ( f . getModifiers ());
injectedMod = retreiver . apply ( mc );
}
catch ( Exception e )
{
Throwables . propagateIfPossible ( e );
2013-12-16 11:47:48 -05:00
FMLLog . log ( getModId (), Level . WARN , e , "Attempting to load @%s in class %s for %s and failing" , annotationName , targets . getClassName (), mc . getModId ());
2012-08-26 10:45:00 -04:00
}
}
if ( f != null )
{
Object target = null ;
if ( ! isStatic )
{
target = modInstance ;
if ( ! modInstance . getClass (). equals ( clz ))
{
2013-12-16 11:47:48 -05:00
FMLLog . log ( getModId (), Level . WARN , "Unable to inject @%s in non-static field %s.%s for %s as it is NOT the primary mod instance" , annotationName , targets . getClassName (), targets . getObjectName (), mc . getModId ());
2012-08-26 10:45:00 -04:00
continue ;
}
}
f . set ( target , injectedMod );
}
}
}
2012-07-22 11:56:38 -02:30
@Subscribe
2012-07-23 16:33:17 -02:30
public void constructMod ( FMLConstructionEvent event )
2012-06-06 01:43:49 -07:00
{
2012-07-30 00:33:21 -04:00
try
2012-07-22 11:56:38 -02:30
{
ModClassLoader modClassLoader = event . getModClassLoader ();
modClassLoader . addFile ( source );
2013-09-25 11:46:11 -04:00
modClassLoader . clearNegativeCacheFor ( candidate . getClassList ());
2012-07-23 16:33:17 -02:30
Class <?> clazz = Class . forName ( className , true , modClassLoader );
2012-12-17 14:30:51 -05:00
Certificate [] certificates = clazz . getProtectionDomain (). getCodeSource (). getCertificates ();
int len = 0 ;
if ( certificates != null )
{
len = certificates . length ;
}
2012-12-17 19:55:46 -05:00
Builder < String > certBuilder = ImmutableList . < String > builder ();
2012-12-17 14:30:51 -05:00
for ( int i = 0 ; i < len ; i ++ )
{
certBuilder . add ( CertificateHelper . getFingerprint ( certificates [ i ] ));
}
2012-12-17 19:55:46 -05:00
ImmutableList < String > certList = certBuilder . build ();
sourceFingerprints = ImmutableSet . copyOf ( certList );
2012-12-17 14:30:51 -05:00
String expectedFingerprint = ( String ) descriptor . get ( "certificateFingerprint" );
2012-12-18 16:39:48 -05:00
fingerprintNotPresent = true ;
2012-12-25 15:59:30 -08:00
if ( expectedFingerprint != null && ! expectedFingerprint . isEmpty ())
2012-12-17 14:30:51 -05:00
{
2012-12-25 15:59:30 -08:00
if ( ! sourceFingerprints . contains ( expectedFingerprint ))
2012-12-17 14:30:51 -05:00
{
2013-12-16 11:47:48 -05:00
Level warnLevel = Level . ERROR ;
2012-12-25 15:59:30 -08:00
if ( source . isDirectory ())
{
2013-12-16 11:47:48 -05:00
warnLevel = Level . TRACE ;
2012-12-25 15:59:30 -08:00
}
2013-01-30 18:57:21 -05:00
FMLLog . log ( getModId (), warnLevel , "The mod %s is expecting signature %s for source %s, however there is no signature matching that description" , getModId (), expectedFingerprint , source . getName ());
2012-12-25 15:59:30 -08:00
}
else
{
certificate = certificates [ certList . indexOf ( expectedFingerprint ) ] ;
fingerprintNotPresent = false ;
2012-12-17 14:30:51 -05:00
}
2012-12-17 19:55:46 -05:00
}
2012-12-25 15:59:30 -08:00
2013-11-10 11:49:06 -05:00
@SuppressWarnings ( "unchecked" )
2013-11-05 22:23:24 -05:00
List < Map < String , Object >> props = ( List < Map < String , Object >> ) descriptor . get ( "customProperties" );
if ( props != null )
2013-06-27 08:38:11 -04:00
{
com . google . common . collect . ImmutableMap . Builder < String , String > builder = ImmutableMap . < String , String > builder ();
2013-11-05 22:23:24 -05:00
for ( Map < String , Object > p : props )
2013-06-27 08:38:11 -04:00
{
2013-11-05 22:23:24 -05:00
builder . put (( String ) p . get ( "k" ),( String ) p . get ( "v" ));
2013-06-27 08:38:11 -04:00
}
customModProperties = builder . build ();
}
else
{
customModProperties = EMPTY_PROPERTIES ;
}
2013-06-26 14:52:56 -04:00
Method factoryMethod = gatherAnnotations ( clazz );
modInstance = getLanguageAdapter (). getNewInstance ( this , clazz , modClassLoader , factoryMethod );
2013-12-06 14:52:33 -05:00
NetworkRegistry . INSTANCE . register ( this , clazz , ( String )( descriptor . containsKey ( "acceptableRemoteVersions" ) ? descriptor . get ( "acceptableRemoteVersions" ) : null ), event . getASMHarvestedData ());
2012-12-17 14:30:51 -05:00
if ( fingerprintNotPresent )
{
2012-12-25 15:59:30 -08:00
eventBus . post ( new FMLFingerprintViolationEvent ( source . isDirectory (), source , ImmutableSet . copyOf ( this . sourceFingerprints ), expectedFingerprint ));
2012-12-17 14:30:51 -05:00
}
2013-04-20 23:31:22 -04:00
ProxyInjector . inject ( this , event . getASMHarvestedData (), FMLCommonHandler . instance (). getSide (), getLanguageAdapter ());
2012-08-26 10:45:00 -04:00
processFieldAnnotations ( event . getASMHarvestedData ());
2012-07-22 11:56:38 -02:30
}
2012-07-23 16:33:17 -02:30
catch ( Throwable e )
2012-07-22 11:56:38 -02:30
{
controller . errorOccurred ( this , e );
Throwables . propagateIfPossible ( e );
}
2012-06-06 01:43:49 -07:00
}
2012-07-30 00:33:21 -04:00
2012-07-23 16:33:17 -02:30
@Subscribe
2012-10-24 16:39:55 -04:00
public void handleModStateEvent ( FMLEvent event )
2012-07-23 16:33:17 -02:30
{
2013-06-26 14:52:56 -04:00
if ( ! eventMethods . containsKey ( event . getClass ()))
2012-07-23 16:33:17 -02:30
{
2012-08-02 09:31:03 -02:30
return ;
2012-07-23 16:33:17 -02:30
}
try
{
2013-06-26 14:52:56 -04:00
for ( Method m : eventMethods . get ( event . getClass ()))
2012-07-23 16:33:17 -02:30
{
2012-07-30 00:33:21 -04:00
m . invoke ( modInstance , event );
2012-07-23 16:33:17 -02:30
}
}
catch ( Throwable t )
{
controller . errorOccurred ( this , t );
}
}
2012-07-30 17:01:27 -04:00
@Override
public ArtifactVersion getProcessedVersion ()
{
if ( processedVersion == null )
{
processedVersion = new DefaultArtifactVersion ( getModId (), getVersion ());
}
return processedVersion ;
}
2012-08-04 11:26:51 -04:00
@Override
public boolean isImmutable ()
{
return false ;
}
2012-08-06 09:52:42 -04:00
@Override
public boolean isNetworkMod ()
{
return isNetworkMod ;
}
2012-08-26 10:45:00 -04:00
@Override
public String getDisplayVersion ()
{
return modMetadata . version ;
}
2012-10-02 01:29:46 -04:00
@Override
public VersionRange acceptableMinecraftVersionRange ()
{
return minecraftAccepted ;
}
2012-12-17 19:55:46 -05:00
@Override
public Certificate getSigningCertificate ()
{
return certificate ;
}
2013-04-21 13:58:18 -04:00
@Override
public String toString ()
{
return "FMLMod:" + getModId () + "{" + getVersion () + "}" ;
}
2013-06-27 08:38:11 -04:00
@Override
public Map < String , String > getCustomModProperties ()
{
return customModProperties ;
}
2013-07-02 11:11:50 -04:00
@Override
public Class <?> getCustomResourcePackClass ()
{
try
{
return getSource (). isDirectory () ? Class . forName ( "cpw.mods.fml.client.FMLFolderResourcePack" , true , getClass (). getClassLoader ()) : Class . forName ( "cpw.mods.fml.client.FMLFileResourcePack" , true , getClass (). getClassLoader ());
}
catch ( ClassNotFoundException e )
{
return null ;
}
}
2013-09-27 10:45:20 -04:00
@Override
public Map < String , String > getSharedModDescriptor ()
{
Map < String , String > descriptor = Maps . newHashMap ();
descriptor . put ( "modsystem" , "FML" );
descriptor . put ( "id" , getModId ());
descriptor . put ( "version" , getDisplayVersion ());
descriptor . put ( "name" , getName ());
descriptor . put ( "url" , modMetadata . url );
descriptor . put ( "authors" , modMetadata . getAuthorList ());
descriptor . put ( "description" , modMetadata . description );
return descriptor ;
}
2012-03-30 10:11:13 -04:00
}