2012-03-30 14:11:13 +00:00
/ *
2016-06-23 03:49:47 +00:00
* Minecraft Forge
* Copyright ( c ) 2016 .
2012-04-05 14:07:52 +00:00
*
2016-06-23 03:49:47 +00: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 version 2 . 1
* of the License .
2012-04-05 14:07:52 +00:00
*
2016-06-23 03:49:47 +00: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 14:07:52 +00:00
*
2016-06-23 03:49:47 +00: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-03-30 14:11:13 +00:00
* /
2014-09-23 05:01:24 +00:00
package net.minecraftforge.fml.common ;
2012-03-30 14:11:13 +00:00
2012-04-18 18:03:30 +00:00
import java.io.File ;
2012-09-17 01:05:11 +00:00
import java.io.FileInputStream ;
2012-07-23 19:03:17 +00:00
import java.lang.annotation.Annotation ;
import java.lang.reflect.Field ;
import java.lang.reflect.Method ;
2012-08-26 14:45:00 +00:00
import java.lang.reflect.Modifier ;
2015-11-04 22:37:15 +00:00
import java.net.MalformedURLException ;
import java.net.URL ;
2012-12-17 19:30:51 +00:00
import java.security.cert.Certificate ;
2012-07-30 04:33:21 +00:00
import java.util.Arrays ;
2012-04-03 03:06:30 +00:00
import java.util.List ;
2016-07-23 23:57:13 +00:00
import java.util.Locale ;
2012-05-11 21:31:28 +00:00
import java.util.Map ;
2012-09-17 01:05:11 +00:00
import java.util.Properties ;
2012-08-23 17:43:25 +00:00
import java.util.Set ;
2014-09-23 05:01:24 +00:00
2016-05-29 09:37:37 +00:00
import net.minecraftforge.common.MinecraftForge ;
2016-10-11 05:15:35 +00:00
import net.minecraftforge.common.config.Config ;
import net.minecraftforge.common.config.ConfigManager ;
2014-09-23 05:01:24 +00:00
import net.minecraftforge.fml.common.Mod.Instance ;
import net.minecraftforge.fml.common.Mod.Metadata ;
2015-02-03 11:21:27 +00:00
import net.minecraftforge.fml.common.asm.transformers.BlamingTransformer ;
2014-09-23 05:01:24 +00:00
import net.minecraftforge.fml.common.discovery.ASMDataTable ;
import net.minecraftforge.fml.common.discovery.ModCandidate ;
import net.minecraftforge.fml.common.discovery.ASMDataTable.ASMData ;
import net.minecraftforge.fml.common.event.FMLConstructionEvent ;
import net.minecraftforge.fml.common.event.FMLEvent ;
import net.minecraftforge.fml.common.event.FMLFingerprintViolationEvent ;
import net.minecraftforge.fml.common.network.NetworkRegistry ;
import net.minecraftforge.fml.common.versioning.ArtifactVersion ;
import net.minecraftforge.fml.common.versioning.DefaultArtifactVersion ;
import net.minecraftforge.fml.common.versioning.VersionParser ;
import net.minecraftforge.fml.common.versioning.VersionRange ;
2015-02-22 02:33:30 +00:00
import net.minecraftforge.fml.relauncher.Side ;
2014-09-23 05:01:24 +00:00
2016-07-23 23:57:13 +00:00
import org.apache.commons.lang3.StringUtils ;
2013-12-16 16:47:48 +00:00
import org.apache.logging.log4j.Level ;
2014-09-23 05:01:24 +00:00
2012-09-17 01:05:11 +00:00
import java.util.zip.ZipEntry ;
import java.util.zip.ZipFile ;
2012-04-03 03:06:30 +00:00
2012-08-26 14:45:00 +00:00
import com.google.common.base.Function ;
2012-08-14 17:36:29 +00:00
import com.google.common.base.Strings ;
2012-07-22 14:26:38 +00:00
import com.google.common.base.Throwables ;
2012-07-23 19:03:17 +00:00
import com.google.common.collect.ArrayListMultimap ;
2012-12-18 00:55:46 +00:00
import com.google.common.collect.ImmutableList ;
import com.google.common.collect.ImmutableList.Builder ;
2013-06-27 12:38:11 +00:00
import com.google.common.collect.ImmutableMap ;
2012-12-17 19:30:51 +00:00
import com.google.common.collect.ImmutableSet ;
2013-06-26 18:52:56 +00:00
import com.google.common.collect.ListMultimap ;
2012-07-22 14:26:38 +00:00
import com.google.common.collect.Lists ;
2013-09-27 14:45:20 +00:00
import com.google.common.collect.Maps ;
2012-08-26 14:45:00 +00:00
import com.google.common.collect.SetMultimap ;
2012-08-23 17:43:25 +00:00
import com.google.common.collect.Sets ;
2012-07-22 14:26:38 +00:00
import com.google.common.eventbus.EventBus ;
import com.google.common.eventbus.Subscribe ;
2012-04-05 14:07:52 +00:00
public class FMLModContainer implements ModContainer
{
private Object modInstance ;
2012-04-18 18:03:30 +00:00
private File source ;
2012-05-15 20:19:46 +00:00
private ModMetadata modMetadata ;
2012-07-22 14:26:38 +00:00
private String className ;
private Map < String , Object > descriptor ;
2012-07-23 19:03:17 +00:00
private boolean enabled = true ;
2012-08-26 14:45:00 +00:00
private String internalVersion ;
2012-07-22 14:26:38 +00:00
private boolean overridesMetadata ;
private EventBus eventBus ;
private LoadController controller ;
2012-07-30 21:01:27 +00:00
private DefaultArtifactVersion processedVersion ;
2012-04-05 14:07:52 +00:00
2012-08-16 17:55:42 +00:00
private String annotationDependencies ;
2012-10-02 05:29:46 +00:00
private VersionRange minecraftAccepted ;
2012-12-17 19:30:51 +00:00
private boolean fingerprintNotPresent ;
private Set < String > sourceFingerprints ;
2012-12-18 00:55:46 +00:00
private Certificate certificate ;
2013-03-08 01:22:24 +00:00
private String modLanguage ;
private ILanguageAdapter languageAdapter ;
2013-12-17 15:51:00 +00:00
private Disableable disableability ;
2015-05-27 15:59:10 +00:00
private ListMultimap < Class < ? extends FMLEvent > , Method > eventMethods ;
2013-06-27 12:38:11 +00:00
private Map < String , String > customModProperties ;
2013-09-25 15:46:11 +00:00
private ModCandidate candidate ;
2015-11-04 22:37:15 +00:00
private URL updateJSONUrl ;
2016-05-04 01:26:52 +00:00
private int classVersion ;
2012-08-04 15:26:51 +00:00
2015-05-27 15:59:10 +00:00
public FMLModContainer ( String className , ModCandidate container , Map < String , Object > modDescriptor )
2012-04-05 14:07:52 +00:00
{
2012-07-22 14:26:38 +00:00
this . className = className ;
2013-09-25 15:46:11 +00:00
this . source = container . getModContainer ( ) ;
this . candidate = container ;
2012-07-22 14:26:38 +00:00
this . descriptor = modDescriptor ;
2013-06-26 18:52:56 +00:00
this . eventMethods = ArrayListMultimap . create ( ) ;
2015-04-11 22:02:00 +00:00
2015-05-27 15:59:10 +00:00
this . modLanguage = ( String ) modDescriptor . get ( " modLanguage " ) ;
2015-04-11 22:02:00 +00:00
String languageAdapterType = ( String ) modDescriptor . get ( " modLanguageAdapter " ) ;
if ( Strings . isNullOrEmpty ( languageAdapterType ) )
2015-04-11 16:36:16 +00:00
{
this . languageAdapter = " scala " . equals ( modLanguage ) ? new ILanguageAdapter . ScalaAdapter ( ) : new ILanguageAdapter . JavaAdapter ( ) ;
}
else
2015-05-27 15:59:10 +00:00
{
// Delay loading of the adapter until the mod is on the classpath, in case the mod itself contains it.
this . languageAdapter = null ;
FMLLog . finer ( " Using custom language adapter %s for %s (modid: %s) " , languageAdapterType , this . className , getModId ( ) ) ;
}
2016-07-23 23:57:13 +00:00
sanityCheckModId ( ) ;
2015-05-27 15:59:10 +00:00
}
2016-07-23 23:57:13 +00:00
private void sanityCheckModId ( )
{
String modid = ( String ) this . descriptor . get ( " modid " ) ;
if ( Strings . isNullOrEmpty ( modid ) )
{
throw new IllegalArgumentException ( " Modid cannot be null or empty " ) ;
}
if ( modid . length ( ) > 64 ) {
FMLLog . bigWarning ( " The modid %s is longer than the recommended maximum of 64 characters. Truncation will be enforced in 1.11 " , modid ) ;
}
if ( ! modid . equals ( modid . toLowerCase ( Locale . ENGLISH ) ) )
{
FMLLog . bigWarning ( " The modid %s is not the same as it's lowercase version. Lowercasing will be enforced in 1.11 " , modid ) ;
}
}
2015-05-27 15:59:10 +00:00
private ILanguageAdapter getLanguageAdapter ( )
{
if ( languageAdapter = = null )
2015-04-11 16:36:16 +00:00
{
try
{
2015-05-27 15:59:10 +00:00
languageAdapter = ( ILanguageAdapter ) Class . forName ( ( String ) descriptor . get ( " modLanguageAdapter " ) , true , Loader . instance ( ) . getModClassLoader ( ) ) . newInstance ( ) ;
2015-04-11 16:36:16 +00:00
}
catch ( Exception ex )
{
2015-05-27 15:59:10 +00:00
FMLLog . log ( Level . ERROR , ex , " Error constructing custom mod language adapter referenced by %s (modid: %s) " , this . className , getModId ( ) ) ;
throw new RuntimeException ( ex ) ;
2015-04-11 16:36:16 +00:00
}
}
2013-03-08 01:22:24 +00:00
return languageAdapter ;
}
2015-05-27 15:59:10 +00:00
2012-04-05 14:07:52 +00:00
@Override
2012-07-22 14:26:38 +00:00
public String getModId ( )
2012-04-05 14:07:52 +00:00
{
2015-05-27 15:59:10 +00:00
return ( String ) descriptor . get ( " modid " ) ;
2012-04-05 14:07:52 +00:00
}
@Override
public String getName ( )
{
2012-07-22 14:26:38 +00:00
return modMetadata . name ;
2012-05-10 13:42:31 +00:00
}
2012-04-05 14:07:52 +00:00
@Override
2012-07-22 14:26:38 +00:00
public String getVersion ( )
2012-04-05 14:07:52 +00:00
{
2012-08-26 14:45:00 +00:00
return internalVersion ;
2012-04-05 14:07:52 +00:00
}
@Override
2012-04-18 18:03:30 +00:00
public File getSource ( )
2012-04-05 14:07:52 +00:00
{
return source ;
}
@Override
2012-07-22 14:26:38 +00:00
public ModMetadata getMetadata ( )
2012-04-05 14:07:52 +00:00
{
2012-07-22 14:26:38 +00:00
return modMetadata ;
2012-04-05 14:07:52 +00:00
}
@Override
2012-07-22 14:26:38 +00:00
public void bindMetadata ( MetadataCollection mc )
2012-04-05 14:07:52 +00:00
{
2012-07-23 19:03:17 +00:00
modMetadata = mc . getMetadataForId ( getModId ( ) , descriptor ) ;
2012-07-30 04:33:21 +00:00
2012-09-25 22:57:42 +00:00
if ( descriptor . containsKey ( " useMetadata " ) )
2012-07-22 14:26:38 +00:00
{
2016-03-23 14:34:48 +00:00
overridesMetadata = ! ( ( Boolean ) descriptor . get ( " useMetadata " ) ) ;
2012-07-22 14:26:38 +00:00
}
2012-07-30 04:33:21 +00:00
2012-07-22 14:26:38 +00:00
if ( overridesMetadata | | ! modMetadata . useDependencyInformation )
{
2012-08-23 17:43:25 +00:00
Set < ArtifactVersion > requirements = Sets . newHashSet ( ) ;
2012-07-30 21:01:27 +00:00
List < ArtifactVersion > dependencies = Lists . newArrayList ( ) ;
List < ArtifactVersion > dependants = Lists . newArrayList ( ) ;
2015-05-27 15:59:10 +00:00
annotationDependencies = ( String ) descriptor . get ( " dependencies " ) ;
2012-08-16 17:55:42 +00:00
Loader . instance ( ) . computeDependencies ( annotationDependencies , requirements , dependencies , dependants ) ;
2015-04-25 05:30:17 +00:00
dependants . addAll ( Loader . instance ( ) . getInjectedBefore ( getModId ( ) ) ) ;
dependencies . addAll ( Loader . instance ( ) . getInjectedAfter ( getModId ( ) ) ) ;
2012-07-22 14:26:38 +00:00
modMetadata . requiredMods = requirements ;
modMetadata . dependencies = dependencies ;
modMetadata . dependants = dependants ;
2013-12-16 16:47:48 +00:00
FMLLog . log ( getModId ( ) , Level . TRACE , " Parsed dependency info : %s %s %s " , requirements , dependencies , dependants ) ;
2012-07-22 14:26:38 +00:00
}
2012-08-23 20:46:23 +00:00
else
{
2013-12-16 16:47:48 +00:00
FMLLog . log ( getModId ( ) , Level . TRACE , " Using mcmod dependency info : %s %s %s " , modMetadata . requiredMods , modMetadata . dependencies , modMetadata . dependants ) ;
2012-08-23 20:46:23 +00:00
}
2012-08-14 17:36:29 +00:00
if ( Strings . isNullOrEmpty ( modMetadata . name ) )
{
2015-05-27 15:59:10 +00:00
FMLLog . log ( getModId ( ) , Level . INFO , " Mod %s is missing the required element 'name'. Substituting %s " , getModId ( ) , getModId ( ) ) ;
2012-08-14 17:36:29 +00:00
modMetadata . name = getModId ( ) ;
}
2015-05-27 15:59:10 +00:00
internalVersion = ( String ) descriptor . get ( " version " ) ;
2012-09-21 21:39:52 +00:00
if ( Strings . isNullOrEmpty ( internalVersion ) )
2012-09-17 01:05:11 +00:00
{
2012-09-17 01:42:59 +00:00
Properties versionProps = searchForVersionProperties ( ) ;
if ( versionProps ! = null )
{
2015-05-27 15:59:10 +00:00
internalVersion = versionProps . getProperty ( getModId ( ) + " .version " ) ;
2013-12-16 16:47:48 +00:00
FMLLog . log ( getModId ( ) , Level . DEBUG , " Found version %s for mod %s in version.properties, using " , internalVersion , getModId ( ) ) ;
2012-09-17 01:42:59 +00:00
}
2012-09-17 01:05:11 +00:00
}
2012-08-26 14:45:00 +00:00
if ( Strings . isNullOrEmpty ( internalVersion ) & & ! Strings . isNullOrEmpty ( modMetadata . version ) )
{
2013-12-16 16:47:48 +00: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-17 00:56:19 +00:00
internalVersion = modMetadata . version ;
2012-08-26 14:45:00 +00:00
}
if ( Strings . isNullOrEmpty ( internalVersion ) )
2012-08-23 17:43:25 +00:00
{
2013-12-16 16:47:48 +00: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 14:45:00 +00:00
modMetadata . version = internalVersion = " 1.0 " ;
2012-08-23 17:43:25 +00:00
}
2012-10-02 05:29:46 +00:00
2015-05-27 15:59:10 +00:00
String mcVersionString = ( String ) descriptor . get ( " acceptedMinecraftVersions " ) ;
2015-12-31 22:40:17 +00:00
if ( " [1.8.8] " . equals ( mcVersionString ) ) mcVersionString = " [1.8.8,1.8.9] " ; // MC 1.8.8 and 1.8.9 is forward SRG compatible so accept these versions by default.
2016-06-29 04:25:04 +00:00
if ( " [1.9.4] " . equals ( mcVersionString ) | |
" [1.9,1.9.4] " . equals ( mcVersionString ) | |
" [1.9.4,1.10) " . equals ( mcVersionString ) | |
" [1.10] " . equals ( mcVersionString ) )
mcVersionString = " [1.9.4,1.10.2] " ;
2012-10-02 05:29:46 +00:00
if ( ! Strings . isNullOrEmpty ( mcVersionString ) )
{
minecraftAccepted = VersionParser . parseRange ( mcVersionString ) ;
}
else
{
minecraftAccepted = Loader . instance ( ) . getMinecraftModContainer ( ) . getStaticVersionRange ( ) ;
}
2015-11-04 22:37:15 +00:00
String jsonURL = ( String ) descriptor . get ( " updateJSON " ) ;
if ( ! Strings . isNullOrEmpty ( jsonURL ) )
{
try
{
this . updateJSONUrl = new URL ( jsonURL ) ;
}
catch ( MalformedURLException e )
{
FMLLog . log ( getModId ( ) , Level . DEBUG , " Specified json URL invalid: %s " , jsonURL ) ;
}
}
2012-04-05 14:07:52 +00:00
}
2012-09-17 01:42:59 +00:00
public Properties searchForVersionProperties ( )
2012-09-17 01:05:11 +00:00
{
try
{
2015-05-27 15:59:10 +00: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-17 01:42:59 +00:00
Properties version = null ;
if ( getSource ( ) . isFile ( ) )
{
ZipFile source = new ZipFile ( getSource ( ) ) ;
ZipEntry versionFile = source . getEntry ( " version.properties " ) ;
2015-05-27 15:59:10 +00:00
if ( versionFile ! = null )
2012-09-17 01:42:59 +00:00
{
version = new Properties ( ) ;
version . load ( source . getInputStream ( versionFile ) ) ;
}
source . close ( ) ;
}
else if ( getSource ( ) . isDirectory ( ) )
2012-09-17 01:05:11 +00:00
{
2015-05-27 15:59:10 +00:00
File propsFile = new File ( getSource ( ) , " version.properties " ) ;
2012-09-17 01:42:59 +00:00
if ( propsFile . exists ( ) & & propsFile . isFile ( ) )
{
version = new Properties ( ) ;
FileInputStream fis = new FileInputStream ( propsFile ) ;
version . load ( fis ) ;
fis . close ( ) ;
}
2012-09-17 01:05:11 +00:00
}
return version ;
}
catch ( Exception e )
{
Throwables . propagateIfPossible ( e ) ;
2013-12-16 16:47:48 +00:00
FMLLog . log ( getModId ( ) , Level . TRACE , " Failed to find a usable version.properties file " ) ;
2012-09-17 01:05:11 +00:00
return null ;
}
}
2012-04-05 14:07:52 +00:00
@Override
2012-07-22 14:26:38 +00:00
public void setEnabledState ( boolean enabled )
2012-04-05 14:07:52 +00:00
{
2012-07-22 14:26:38 +00:00
this . enabled = enabled ;
2012-04-05 14:07:52 +00:00
}
@Override
2012-08-23 17:43:25 +00:00
public Set < ArtifactVersion > getRequirements ( )
2012-04-05 14:07:52 +00:00
{
2012-07-22 14:26:38 +00:00
return modMetadata . requiredMods ;
2012-04-05 14:07:52 +00:00
}
@Override
2012-07-30 21:01:27 +00:00
public List < ArtifactVersion > getDependencies ( )
2012-04-05 14:07:52 +00:00
{
2012-07-22 14:26:38 +00:00
return modMetadata . dependencies ;
2012-04-05 14:07:52 +00:00
}
@Override
2012-07-30 21:01:27 +00:00
public List < ArtifactVersion > getDependants ( )
2012-04-05 14:07:52 +00:00
{
2012-07-22 14:26:38 +00:00
return modMetadata . dependants ;
2012-04-05 14:07:52 +00:00
}
@Override
2012-07-22 14:26:38 +00:00
public String getSortingRules ( )
2012-04-05 14:07:52 +00:00
{
2012-08-23 18:28:49 +00:00
return ( ( overridesMetadata | | ! modMetadata . useDependencyInformation ) ? Strings . nullToEmpty ( annotationDependencies ) : modMetadata . printableSortingRules ( ) ) ;
2012-04-05 14:07:52 +00:00
}
@Override
2012-07-22 14:26:38 +00:00
public boolean matches ( Object mod )
2012-04-05 14:07:52 +00:00
{
2012-07-22 14:26:38 +00:00
return mod = = modInstance ;
2012-04-05 14:07:52 +00:00
}
2012-04-08 06:00:57 +00:00
@Override
2012-07-22 14:26:38 +00:00
public Object getMod ( )
2012-04-08 06:00:57 +00:00
{
2012-07-22 14:26:38 +00:00
return modInstance ;
2012-04-08 06:00:57 +00:00
}
2012-04-09 14:18:24 +00:00
2012-06-02 19:13:55 +00:00
@Override
2012-07-22 14:26:38 +00:00
public boolean registerBus ( EventBus bus , LoadController controller )
2012-06-02 19:13:55 +00:00
{
2012-07-22 14:26:38 +00:00
if ( this . enabled )
{
2013-12-16 16:47:48 +00:00
FMLLog . log ( getModId ( ) , Level . DEBUG , " Enabling mod %s " , getModId ( ) ) ;
2012-07-22 14:26:38 +00:00
this . eventBus = bus ;
this . controller = controller ;
eventBus . register ( this ) ;
return true ;
}
else
{
return false ;
}
2012-06-02 19:13:55 +00:00
}
2012-07-30 04:33:21 +00:00
2013-11-10 16:49:06 +00:00
@SuppressWarnings ( " unchecked " )
2013-06-26 18:52:56 +00:00
private Method gatherAnnotations ( Class < ? > clazz ) throws Exception
2012-07-23 19:03:17 +00:00
{
2013-06-26 18:52:56 +00:00
Method factoryMethod = null ;
2012-07-23 19:03:17 +00:00
for ( Method m : clazz . getDeclaredMethods ( ) )
{
for ( Annotation a : m . getAnnotations ( ) )
{
2013-11-10 16:58:34 +00:00
if ( a . annotationType ( ) . equals ( Mod . EventHandler . class ) )
2013-06-26 18:52:56 +00:00
{
2014-02-25 20:30:29 +00:00
if ( m . getParameterTypes ( ) . length = = 1 & & FMLEvent . class . isAssignableFrom ( m . getParameterTypes ( ) [ 0 ] ) )
2013-06-26 18:52:56 +00:00
{
m . setAccessible ( true ) ;
2015-05-27 15:59:10 +00:00
eventMethods . put ( ( Class < ? extends FMLEvent > ) m . getParameterTypes ( ) [ 0 ] , m ) ;
2013-06-26 18:52:56 +00:00
}
else
{
2015-05-27 15:59:10 +00: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 18:52:56 +00: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 ) )
{
2015-05-27 15:59:10 +00: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 18:52:56 +00:00
}
else if ( factoryMethod ! = null )
{
2013-12-16 16:47:48 +00: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 18:52:56 +00:00
}
}
2012-07-23 19:03:17 +00:00
}
}
2013-06-26 18:52:56 +00:00
return factoryMethod ;
2012-07-23 19:03:17 +00:00
}
2012-08-26 14:45:00 +00:00
private void processFieldAnnotations ( ASMDataTable asmDataTable ) throws Exception
2012-07-23 19:03:17 +00:00
{
2012-08-26 14:45:00 +00:00
SetMultimap < String , ASMData > annotations = asmDataTable . getAnnotationsFor ( this ) ;
2012-07-30 04:33:21 +00:00
2012-08-26 14:45:00 +00:00
parseSimpleFieldAnnotation ( annotations , Instance . class . getName ( ) , new Function < ModContainer , Object > ( )
2012-07-23 19:03:17 +00:00
{
2014-01-18 04:19:22 +00:00
@Override
2012-08-26 14:45:00 +00:00
public Object apply ( ModContainer mc )
{
return mc . getMod ( ) ;
}
} ) ;
parseSimpleFieldAnnotation ( annotations , Metadata . class . getName ( ) , new Function < ModContainer , Object > ( )
{
2014-01-18 04:19:22 +00:00
@Override
2012-08-26 14:45:00 +00:00
public Object apply ( ModContainer mc )
{
return mc . getMetadata ( ) ;
}
} ) ;
2012-07-23 19:03:17 +00:00
}
2016-03-23 14:34:48 +00:00
private void parseSimpleFieldAnnotation ( SetMultimap < String , ASMData > annotations , String annotationClassName , Function < ModContainer , Object > retriever ) throws IllegalAccessException
2012-08-26 14:45:00 +00:00
{
String [ ] annName = annotationClassName . split ( " \\ . " ) ;
String annotationName = annName [ annName . length - 1 ] ;
for ( ASMData targets : annotations . get ( annotationClassName ) )
{
2015-05-27 15:59:10 +00:00
String targetMod = ( String ) targets . getAnnotationInfo ( ) . get ( " value " ) ;
2012-08-26 14:45:00 +00:00
Field f = null ;
Object injectedMod = null ;
ModContainer mc = this ;
boolean isStatic = false ;
Class < ? > clz = modInstance . getClass ( ) ;
if ( ! Strings . isNullOrEmpty ( targetMod ) )
{
2012-08-26 14:55:55 +00:00
if ( Loader . isModLoaded ( targetMod ) )
{
mc = Loader . instance ( ) . getIndexedModList ( ) . get ( targetMod ) ;
}
else
{
mc = null ;
}
2012-08-26 14:45:00 +00: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 ( ) ) ;
2016-03-23 14:34:48 +00:00
injectedMod = retriever . apply ( mc ) ;
2012-08-26 14:45:00 +00:00
}
catch ( Exception e )
{
Throwables . propagateIfPossible ( e ) ;
2013-12-16 16:47:48 +00: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 14:45:00 +00:00
}
}
if ( f ! = null )
{
Object target = null ;
if ( ! isStatic )
{
target = modInstance ;
if ( ! modInstance . getClass ( ) . equals ( clz ) )
{
2013-12-16 16:47:48 +00: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 14:45:00 +00:00
continue ;
}
}
f . set ( target , injectedMod ) ;
}
}
}
2012-07-22 14:26:38 +00:00
@Subscribe
2012-07-23 19:03:17 +00:00
public void constructMod ( FMLConstructionEvent event )
2012-06-06 08:43:49 +00:00
{
2012-07-30 04:33:21 +00:00
try
2012-07-22 14:26:38 +00:00
{
2015-02-03 11:21:27 +00:00
BlamingTransformer . addClasses ( getModId ( ) , candidate . getClassList ( ) ) ;
2012-07-22 14:26:38 +00:00
ModClassLoader modClassLoader = event . getModClassLoader ( ) ;
modClassLoader . addFile ( source ) ;
2013-09-25 15:46:11 +00:00
modClassLoader . clearNegativeCacheFor ( candidate . getClassList ( ) ) ;
2016-05-29 09:37:37 +00:00
//Only place I could think to add this...
MinecraftForge . preloadCrashClasses ( event . getASMHarvestedData ( ) , getModId ( ) , candidate . getClassList ( ) ) ;
2012-07-23 19:03:17 +00:00
Class < ? > clazz = Class . forName ( className , true , modClassLoader ) ;
2012-12-17 19:30:51 +00:00
Certificate [ ] certificates = clazz . getProtectionDomain ( ) . getCodeSource ( ) . getCertificates ( ) ;
int len = 0 ;
if ( certificates ! = null )
{
len = certificates . length ;
}
2016-03-23 14:34:48 +00:00
Builder < String > certBuilder = ImmutableList . builder ( ) ;
2012-12-17 19:30:51 +00:00
for ( int i = 0 ; i < len ; i + + )
{
certBuilder . add ( CertificateHelper . getFingerprint ( certificates [ i ] ) ) ;
}
2012-12-18 00:55:46 +00:00
ImmutableList < String > certList = certBuilder . build ( ) ;
sourceFingerprints = ImmutableSet . copyOf ( certList ) ;
2012-12-17 19:30:51 +00:00
2015-05-27 15:59:10 +00:00
String expectedFingerprint = ( String ) descriptor . get ( " certificateFingerprint " ) ;
2012-12-17 19:30:51 +00:00
2012-12-18 21:39:48 +00:00
fingerprintNotPresent = true ;
2012-12-25 23:59:30 +00:00
if ( expectedFingerprint ! = null & & ! expectedFingerprint . isEmpty ( ) )
2012-12-17 19:30:51 +00:00
{
2012-12-25 23:59:30 +00:00
if ( ! sourceFingerprints . contains ( expectedFingerprint ) )
2012-12-17 19:30:51 +00:00
{
2013-12-16 16:47:48 +00:00
Level warnLevel = Level . ERROR ;
2012-12-25 23:59:30 +00:00
if ( source . isDirectory ( ) )
{
2013-12-16 16:47:48 +00:00
warnLevel = Level . TRACE ;
2012-12-25 23:59:30 +00:00
}
2013-01-30 23:57:21 +00: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 23:59:30 +00:00
}
else
{
certificate = certificates [ certList . indexOf ( expectedFingerprint ) ] ;
fingerprintNotPresent = false ;
2012-12-17 19:30:51 +00:00
}
2012-12-18 00:55:46 +00:00
}
2012-12-25 23:59:30 +00:00
2013-11-10 16:49:06 +00:00
@SuppressWarnings ( " unchecked " )
2015-05-27 15:59:10 +00:00
List < Map < String , Object > > props = ( List < Map < String , Object > > ) descriptor . get ( " customProperties " ) ;
2013-11-06 03:23:24 +00:00
if ( props ! = null )
2013-06-27 12:38:11 +00:00
{
2016-03-23 14:34:48 +00:00
com . google . common . collect . ImmutableMap . Builder < String , String > builder = ImmutableMap . builder ( ) ;
2013-11-06 03:23:24 +00:00
for ( Map < String , Object > p : props )
2013-06-27 12:38:11 +00:00
{
2015-05-27 15:59:10 +00:00
builder . put ( ( String ) p . get ( " k " ) , ( String ) p . get ( " v " ) ) ;
2013-06-27 12:38:11 +00:00
}
customModProperties = builder . build ( ) ;
}
else
{
customModProperties = EMPTY_PROPERTIES ;
}
2015-05-27 15:59:10 +00:00
Boolean hasDisableableFlag = ( Boolean ) descriptor . get ( " canBeDeactivated " ) ;
2013-12-17 15:51:00 +00:00
boolean hasReverseDepends = ! event . getReverseDependencies ( ) . get ( getModId ( ) ) . isEmpty ( ) ;
if ( hasDisableableFlag ! = null & & hasDisableableFlag )
{
disableability = hasReverseDepends ? Disableable . DEPENDENCIES : Disableable . YES ;
}
else
{
disableability = hasReverseDepends ? Disableable . DEPENDENCIES : Disableable . RESTART ;
}
2013-06-26 18:52:56 +00:00
Method factoryMethod = gatherAnnotations ( clazz ) ;
2015-05-27 15:59:10 +00:00
modInstance = getLanguageAdapter ( ) . getNewInstance ( this , clazz , modClassLoader , factoryMethod ) ;
2013-12-06 19:52:33 +00:00
NetworkRegistry . INSTANCE . register ( this , clazz , ( String ) ( descriptor . containsKey ( " acceptableRemoteVersions " ) ? descriptor . get ( " acceptableRemoteVersions " ) : null ) , event . getASMHarvestedData ( ) ) ;
2012-12-17 19:30:51 +00:00
if ( fingerprintNotPresent )
{
2012-12-25 23:59:30 +00:00
eventBus . post ( new FMLFingerprintViolationEvent ( source . isDirectory ( ) , source , ImmutableSet . copyOf ( this . sourceFingerprints ) , expectedFingerprint ) ) ;
2012-12-17 19:30:51 +00:00
}
2013-04-21 03:31:22 +00:00
ProxyInjector . inject ( this , event . getASMHarvestedData ( ) , FMLCommonHandler . instance ( ) . getSide ( ) , getLanguageAdapter ( ) ) ;
2016-09-18 01:08:42 +00:00
AutomaticEventSubscriber . inject ( this , event . getASMHarvestedData ( ) , FMLCommonHandler . instance ( ) . getSide ( ) ) ;
2016-10-11 05:15:35 +00:00
ConfigManager . load ( this . getModId ( ) , Config . Type . INSTANCE ) ;
2016-09-18 01:08:42 +00:00
2012-08-26 14:45:00 +00:00
processFieldAnnotations ( event . getASMHarvestedData ( ) ) ;
2012-07-22 14:26:38 +00:00
}
2012-07-23 19:03:17 +00:00
catch ( Throwable e )
2012-07-22 14:26:38 +00:00
{
controller . errorOccurred ( this , e ) ;
}
2012-06-06 08:43:49 +00:00
}
2012-07-30 04:33:21 +00:00
2012-07-23 19:03:17 +00:00
@Subscribe
2012-10-24 20:39:55 +00:00
public void handleModStateEvent ( FMLEvent event )
2012-07-23 19:03:17 +00:00
{
2013-06-26 18:52:56 +00:00
if ( ! eventMethods . containsKey ( event . getClass ( ) ) )
2012-07-23 19:03:17 +00:00
{
2012-08-02 12:01:03 +00:00
return ;
2012-07-23 19:03:17 +00:00
}
try
{
2013-06-26 18:52:56 +00:00
for ( Method m : eventMethods . get ( event . getClass ( ) ) )
2012-07-23 19:03:17 +00:00
{
2012-07-30 04:33:21 +00:00
m . invoke ( modInstance , event ) ;
2012-07-23 19:03:17 +00:00
}
}
catch ( Throwable t )
{
controller . errorOccurred ( this , t ) ;
}
}
2012-07-30 21:01:27 +00:00
@Override
public ArtifactVersion getProcessedVersion ( )
{
if ( processedVersion = = null )
{
processedVersion = new DefaultArtifactVersion ( getModId ( ) , getVersion ( ) ) ;
}
return processedVersion ;
}
2015-05-27 15:59:10 +00:00
2012-08-04 15:26:51 +00:00
@Override
public boolean isImmutable ( )
{
return false ;
}
2012-08-06 13:52:42 +00:00
2012-08-26 14:45:00 +00:00
@Override
public String getDisplayVersion ( )
{
return modMetadata . version ;
}
2012-10-02 05:29:46 +00:00
@Override
public VersionRange acceptableMinecraftVersionRange ( )
{
return minecraftAccepted ;
}
2012-12-18 00:55:46 +00:00
@Override
public Certificate getSigningCertificate ( )
{
return certificate ;
}
2013-04-21 17:58:18 +00:00
@Override
public String toString ( )
{
2015-05-27 15:59:10 +00:00
return " FMLMod: " + getModId ( ) + " { " + getVersion ( ) + " } " ;
2013-04-21 17:58:18 +00:00
}
2013-06-27 12:38:11 +00:00
@Override
public Map < String , String > getCustomModProperties ( )
{
return customModProperties ;
}
2013-07-02 15:11:50 +00:00
@Override
public Class < ? > getCustomResourcePackClass ( )
{
try
{
2015-05-27 15:59:10 +00:00
return getSource ( ) . isDirectory ( ) ? Class . forName ( " net.minecraftforge.fml.client.FMLFolderResourcePack " , true , getClass ( ) . getClassLoader ( ) ) : Class . forName ( " net.minecraftforge.fml.client.FMLFileResourcePack " , true , getClass ( ) . getClassLoader ( ) ) ;
2013-07-02 15:11:50 +00:00
}
catch ( ClassNotFoundException e )
{
return null ;
}
}
2015-05-27 15:59:10 +00:00
2013-09-27 14:45:20 +00:00
@Override
public Map < String , String > getSharedModDescriptor ( )
{
2015-05-27 15:59:10 +00:00
Map < String , String > descriptor = Maps . newHashMap ( ) ;
2013-09-27 14:45:20 +00:00
descriptor . put ( " modsystem " , " FML " ) ;
descriptor . put ( " id " , getModId ( ) ) ;
2015-05-27 15:59:10 +00:00
descriptor . put ( " version " , getDisplayVersion ( ) ) ;
2013-09-27 14:45:20 +00:00
descriptor . put ( " name " , getName ( ) ) ;
descriptor . put ( " url " , modMetadata . url ) ;
descriptor . put ( " authors " , modMetadata . getAuthorList ( ) ) ;
descriptor . put ( " description " , modMetadata . description ) ;
return descriptor ;
}
2013-12-17 15:51:00 +00:00
@Override
public Disableable canBeDisabled ( )
{
return disableability ;
}
2014-01-02 16:51:16 +00:00
@Override
public String getGuiClassName ( )
{
2015-05-27 15:59:10 +00:00
return ( String ) descriptor . get ( " guiFactory " ) ;
2014-01-02 16:51:16 +00:00
}
2014-01-25 11:17:14 +00:00
@Override
public List < String > getOwnedPackages ( )
{
return candidate . getContainedPackages ( ) ;
}
2015-02-22 02:33:30 +00:00
2015-02-22 03:48:48 +00:00
private boolean isTrue ( Boolean value )
{
2015-05-27 15:59:10 +00:00
if ( value = = null )
{
return false ;
}
2016-03-23 14:34:48 +00:00
return value ;
2015-02-22 03:48:48 +00:00
}
2015-02-22 02:33:30 +00:00
@Override
public boolean shouldLoadInEnvironment ( )
{
2015-02-22 03:48:48 +00:00
boolean clientSideOnly = isTrue ( ( Boolean ) descriptor . get ( " clientSideOnly " ) ) ;
boolean serverSideOnly = isTrue ( ( Boolean ) descriptor . get ( " serverSideOnly " ) ) ;
2015-02-22 02:33:30 +00:00
if ( clientSideOnly & & serverSideOnly )
2015-05-27 15:59:10 +00:00
{
2015-02-22 02:33:30 +00:00
throw new RuntimeException ( " Mod annotation claims to be both client and server side only! " ) ;
2015-05-27 15:59:10 +00:00
}
2015-02-22 02:33:30 +00:00
Side side = FMLCommonHandler . instance ( ) . getSide ( ) ;
if ( clientSideOnly & & side ! = Side . CLIENT )
{
2015-04-02 16:33:19 +00:00
FMLLog . info ( " Disabling mod %s it is client side only. " , getModId ( ) ) ;
2015-02-22 02:33:30 +00:00
return false ;
}
if ( serverSideOnly & & side ! = Side . SERVER )
{
2015-04-02 16:33:19 +00:00
FMLLog . info ( " Disabling mod %s it is server side only. " , getModId ( ) ) ;
2015-02-22 02:33:30 +00:00
return false ;
}
return true ;
}
2015-11-04 22:37:15 +00:00
@Override
public URL getUpdateUrl ( )
{
return updateJSONUrl ;
}
2016-05-04 01:26:52 +00:00
@Override
public void setClassVersion ( int classVersion )
{
this . classVersion = classVersion ;
}
@Override
public int getClassVersion ( )
{
return this . classVersion ;
}
2015-05-27 15:59:10 +00:00
}