2012-06-02 19:13:55 +00:00
/ *
2016-06-23 03:49:47 +00:00
* Minecraft Forge
* Copyright ( c ) 2016 .
2013-04-21 03:31:22 +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 .
*
* 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 .
*
* 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-06-02 19:13:55 +00:00
* /
2014-09-23 05:01:24 +00:00
package net.minecraftforge.fml.common ;
2012-06-02 19:13:55 +00:00
import java.lang.reflect.Field ;
2012-08-10 21:42:43 +00:00
import java.lang.reflect.Modifier ;
import java.util.Set ;
2014-09-23 05:01:24 +00:00
import net.minecraftforge.fml.common.discovery.ASMDataTable ;
import net.minecraftforge.fml.common.discovery.ASMDataTable.ASMData ;
import net.minecraftforge.fml.relauncher.Side ;
2013-12-16 16:47:48 +00:00
import org.apache.logging.log4j.Level ;
2012-08-10 21:42:43 +00:00
2013-06-06 14:02:48 +00:00
import com.google.common.base.Strings ;
2012-06-02 19:13:55 +00:00
/ * *
* @author cpw
*
* /
public class ProxyInjector
{
2013-04-21 03:31:22 +00:00
public static void inject ( ModContainer mod , ASMDataTable data , Side side , ILanguageAdapter languageAdapter )
2012-06-02 19:13:55 +00:00
{
2012-08-10 21:42:43 +00:00
FMLLog . fine ( " Attempting to inject @SidedProxy classes into %s " , mod . getModId ( ) ) ;
2012-08-11 06:24:29 +00:00
Set < ASMData > targets = data . getAnnotationsFor ( mod ) . get ( SidedProxy . class . getName ( ) ) ;
2012-08-10 21:42:43 +00:00
ClassLoader mcl = Loader . instance ( ) . getModClassLoader ( ) ;
2012-07-02 16:32:41 +00:00
2012-08-10 21:42:43 +00:00
for ( ASMData targ : targets )
2012-06-02 19:13:55 +00:00
{
2012-08-10 21:42:43 +00:00
try
{
2016-10-08 23:27:49 +00:00
//Pull this from the ASM data so we do not prematurely initialize mods with the below Class.forName
String modid = ( String ) targ . getAnnotationInfo ( ) . get ( " modId " ) ;
if ( modid = = null )
{
for ( ASMData a : data . getAll ( Mod . class . getName ( ) ) )
{
2016-10-09 08:22:28 +00:00
if ( isProxyFromMod ( a . getClassName ( ) , targ . getClassName ( ) ) )
2016-10-08 23:27:49 +00:00
{
modid = ( String ) a . getAnnotationInfo ( ) . get ( " modid " ) ;
break ;
}
}
}
2016-10-09 08:22:28 +00:00
if ( modid = = null )
{
FMLLog . warning ( " Unable to determine the associated mod for proxy injection for %s.%s, assuming it's from %s " , targ . getClassName ( ) , targ . getObjectName ( ) , mod . getModId ( ) ) ;
}
else if ( ! modid . equals ( mod . getModId ( ) ) )
2016-10-08 23:27:49 +00:00
{
2016-10-09 08:22:28 +00:00
FMLLog . fine ( " Skipping proxy injection for %s.%s since it is not for mod %s, it should belong to %s " , targ . getClassName ( ) , targ . getObjectName ( ) , mod . getModId ( ) , modid ) ;
2016-10-08 23:27:49 +00:00
continue ;
}
2012-08-10 21:42:43 +00:00
Class < ? > proxyTarget = Class . forName ( targ . getClassName ( ) , true , mcl ) ;
Field target = proxyTarget . getDeclaredField ( targ . getObjectName ( ) ) ;
if ( target = = null )
{
// Impossible?
FMLLog . severe ( " Attempted to load a proxy type into %s.%s but the field was not found " , targ . getClassName ( ) , targ . getObjectName ( ) ) ;
2015-03-27 08:17:57 +00:00
throw new LoaderException ( String . format ( " Attempted to load a proxy type into %s.%s but the field was not found " , targ . getClassName ( ) , targ . getObjectName ( ) ) ) ;
2012-08-10 21:42:43 +00:00
}
2014-01-20 12:55:26 +00:00
target . setAccessible ( true ) ;
2012-07-02 16:32:41 +00:00
2013-06-06 14:02:48 +00:00
SidedProxy annotation = target . getAnnotation ( SidedProxy . class ) ;
String targetType = side . isClient ( ) ? annotation . clientSide ( ) : annotation . serverSide ( ) ;
2016-01-02 06:59:14 +00:00
if ( targetType . equals ( " " ) )
{
targetType = targ . getClassName ( ) + ( side . isClient ( ) ? " $ClientProxy " : " $ServerProxy " ) ;
}
2012-08-10 21:42:43 +00:00
Object proxy = Class . forName ( targetType , true , mcl ) . newInstance ( ) ;
2013-04-21 03:31:22 +00:00
if ( languageAdapter . supportsStatics ( ) & & ( target . getModifiers ( ) & Modifier . STATIC ) = = 0 )
2012-08-10 21:42:43 +00:00
{
FMLLog . severe ( " Attempted to load a proxy type %s into %s.%s, but the field is not static " , targetType , targ . getClassName ( ) , targ . getObjectName ( ) ) ;
2015-03-27 08:17:57 +00:00
throw new LoaderException ( String . format ( " Attempted to load a proxy type %s into %s.%s, but the field is not static " , targetType , targ . getClassName ( ) , targ . getObjectName ( ) ) ) ;
2012-08-10 21:42:43 +00:00
}
if ( ! target . getType ( ) . isAssignableFrom ( proxy . getClass ( ) ) )
{
FMLLog . severe ( " Attempted to load a proxy type %s into %s.%s, but the types don't match " , targetType , targ . getClassName ( ) , targ . getObjectName ( ) ) ;
2015-03-27 08:17:57 +00:00
throw new LoaderException ( String . format ( " Attempted to load a proxy type %s into %s.%s, but the types don't match " , targetType , targ . getClassName ( ) , targ . getObjectName ( ) ) ) ;
2012-08-10 21:42:43 +00:00
}
2013-04-21 03:31:22 +00:00
languageAdapter . setProxy ( target , proxyTarget , proxy ) ;
2012-08-10 21:42:43 +00:00
}
catch ( Exception e )
2012-06-02 19:13:55 +00:00
{
2016-03-23 14:34:48 +00:00
FMLLog . log ( Level . ERROR , e , " An error occurred trying to load a proxy into %s.%s " , targ . getAnnotationInfo ( ) , targ . getClassName ( ) , targ . getObjectName ( ) ) ;
2012-08-10 21:42:43 +00:00
throw new LoaderException ( e ) ;
2012-06-02 19:13:55 +00:00
}
}
2013-05-08 17:04:35 +00:00
// Allow language specific proxy injection.
languageAdapter . setInternalProxies ( mod , side , mcl ) ;
2012-06-02 19:13:55 +00:00
}
2016-10-09 08:22:28 +00:00
/ * *
* Checks if a proxy is part of a mod .
*
* Checks that the proxy is somewhere in the same package that holds the mod .
* For example , the @Mod is ' com . modname . Mod ' , the Proxy is ' com . modname . proxies . ProxyClient '
* The package of the mod is ' com . modname ' , and Proxy is in that package , so it is from the mod .
*
* Compares each path section in a for loop instead of simply using { @link String # startsWith ( String ) }
* because a mod like ' com . modname . Mod ' with package ' com.modname '
* does not own a proxy from ' com . modnametools . proxies . ProxyClient ' even though they start the same .
* /
private static boolean isProxyFromMod ( String modClassName , String proxyClassName )
{
if ( modClassName . equals ( proxyClassName ) )
return true ;
String [ ] modPath = modClassName . split ( " \\ . " ) ;
String [ ] proxyPath = proxyClassName . split ( " \\ . " ) ;
if ( proxyPath . length < modPath . length )
return false ;
for ( int i = 0 ; i < modPath . length - 1 ; i + + )
{
if ( ! modPath [ i ] . equals ( proxyPath [ i ] ) )
{
return false ;
}
}
return true ;
}
2012-06-02 19:13:55 +00:00
}