2014-09-23 05:01:24 +00:00
package net.minecraftforge.fml.common.registry ;
2014-05-25 02:32:24 +00:00
import java.lang.reflect.Field ;
import java.lang.reflect.Method ;
import java.lang.reflect.Modifier ;
2014-09-23 05:01:24 +00:00
2015-11-28 08:01:31 +00:00
import net.minecraft.util.ResourceLocation ;
2014-05-25 02:32:24 +00:00
import org.apache.logging.log4j.Level ;
2014-09-23 05:01:24 +00:00
2014-05-25 02:32:24 +00:00
import com.google.common.base.Throwables ;
2014-09-23 05:01:24 +00:00
2014-05-25 02:32:24 +00:00
import net.minecraft.block.Block ;
2014-05-26 14:58:13 +00:00
import net.minecraft.init.Blocks ;
2014-05-25 02:32:24 +00:00
import net.minecraft.item.Item ;
2014-09-23 05:01:24 +00:00
import net.minecraftforge.fml.common.FMLLog ;
import net.minecraftforge.fml.common.registry.GameRegistry.ObjectHolder ;
2014-05-25 02:32:24 +00:00
/ * *
* Internal class used in tracking { @link ObjectHolder } references
*
* @author cpw
*
* /
class ObjectHolderRef {
private Field field ;
2015-11-28 08:01:31 +00:00
private ResourceLocation injectedObject ;
2014-05-25 02:32:24 +00:00
private boolean isBlock ;
private boolean isItem ;
2015-11-28 08:01:31 +00:00
ObjectHolderRef ( Field field , ResourceLocation injectedObject , boolean extractFromExistingValues )
2014-05-25 02:32:24 +00:00
{
this . field = field ;
this . isBlock = Block . class . isAssignableFrom ( field . getType ( ) ) ;
this . isItem = Item . class . isAssignableFrom ( field . getType ( ) ) ;
if ( extractFromExistingValues )
{
try
{
Object existing = field . get ( null ) ;
2014-05-26 14:58:13 +00:00
// nothing is ever allowed to replace AIR
if ( existing = = null | | existing = = GameData . getBlockRegistry ( ) . getDefaultValue ( ) )
{
this . injectedObject = null ;
this . field = null ;
this . isBlock = false ;
this . isItem = false ;
return ;
}
else
{
2016-05-18 12:11:56 +00:00
ResourceLocation tmp = isBlock ? ForgeRegistries . BLOCKS . getKey ( ( Block ) existing ) :
isItem ? ForgeRegistries . ITEMS . getKey ( ( Item ) existing ) : null ;
2015-11-28 08:01:31 +00:00
this . injectedObject = tmp ;
2014-05-26 14:58:13 +00:00
}
2014-05-25 02:32:24 +00:00
} catch ( Exception e )
{
throw Throwables . propagate ( e ) ;
}
}
else
{
this . injectedObject = injectedObject ;
}
if ( this . injectedObject = = null | | ! isValid ( ) )
{
2015-07-09 21:05:20 +00:00
throw new IllegalStateException ( String . format ( " The ObjectHolder annotation cannot apply to a field that is not an Item or Block (found : %s at %s.%s) " , field . getType ( ) . getName ( ) , field . getClass ( ) . getName ( ) , field . getName ( ) ) ) ;
2014-05-25 02:32:24 +00:00
}
makeWritable ( field ) ;
}
private static Field modifiersField ;
private static Object reflectionFactory ;
private static Method newFieldAccessor ;
private static Method fieldAccessorSet ;
private static void makeWritable ( Field f )
{
try
{
if ( modifiersField = = null )
{
Method getReflectionFactory = Class . forName ( " sun.reflect.ReflectionFactory " ) . getDeclaredMethod ( " getReflectionFactory " ) ;
reflectionFactory = getReflectionFactory . invoke ( null ) ;
newFieldAccessor = Class . forName ( " sun.reflect.ReflectionFactory " ) . getDeclaredMethod ( " newFieldAccessor " , Field . class , boolean . class ) ;
fieldAccessorSet = Class . forName ( " sun.reflect.FieldAccessor " ) . getDeclaredMethod ( " set " , Object . class , Object . class ) ;
modifiersField = Field . class . getDeclaredField ( " modifiers " ) ;
modifiersField . setAccessible ( true ) ;
}
modifiersField . setInt ( f , f . getModifiers ( ) & ~ Modifier . FINAL ) ;
} catch ( Exception e )
{
throw Throwables . propagate ( e ) ;
}
}
public boolean isValid ( )
{
return isBlock | | isItem ;
}
public void apply ( )
{
Object thing ;
if ( isBlock )
2014-05-26 14:58:13 +00:00
{
2016-05-18 12:11:56 +00:00
thing = ForgeRegistries . BLOCKS . getValue ( injectedObject ) ;
if ( thing = = Blocks . AIR )
2014-05-26 14:58:13 +00:00
{
thing = null ;
}
}
else if ( isItem )
{
2016-05-18 12:11:56 +00:00
thing = ForgeRegistries . ITEMS . getValue ( injectedObject ) ;
2014-05-26 14:58:13 +00:00
}
else
{
thing = null ;
}
if ( thing = = null )
{
2015-06-25 18:41:45 +00:00
FMLLog . getLogger ( ) . log ( Level . DEBUG , " Unable to lookup {} for {}. This means the object wasn't registered. It's likely just mod options. " , injectedObject , field ) ;
2014-05-26 14:58:13 +00:00
return ;
}
2014-05-25 02:32:24 +00:00
try
{
Object fieldAccessor = newFieldAccessor . invoke ( reflectionFactory , field , false ) ;
fieldAccessorSet . invoke ( fieldAccessor , null , thing ) ;
}
catch ( Exception e )
{
FMLLog . log ( Level . WARN , e , " Unable to set %s with value %s (%s) " , this . field , thing , this . injectedObject ) ;
}
}
}