2016-06-23 03:49:47 +00:00
/ *
* Minecraft Forge
2018-07-01 21:17:28 +00:00
* Copyright ( c ) 2016 - 2018 .
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
* /
2017-06-19 22:02:18 +00:00
package net.minecraftforge.registries ;
2014-05-25 02:32:24 +00:00
import java.lang.reflect.Field ;
2017-06-19 22:02:18 +00:00
import java.lang.reflect.Modifier ;
2016-10-09 20:34:38 +00:00
import java.util.Collections ;
import java.util.LinkedList ;
import java.util.Queue ;
2014-09-23 05:01:24 +00:00
2015-11-28 08:01:31 +00:00
import net.minecraft.util.ResourceLocation ;
2014-09-23 05:01:24 +00:00
2017-01-11 23:17:56 +00:00
import javax.annotation.Nullable ;
2018-09-06 11:39:01 +00:00
import org.apache.logging.log4j.LogManager ;
import org.apache.logging.log4j.Logger ;
2014-05-25 02:32:24 +00:00
/ * *
* Internal class used in tracking { @link ObjectHolder } references
* /
2016-10-09 22:57:18 +00:00
@SuppressWarnings ( " rawtypes " )
2017-06-19 22:02:18 +00:00
class ObjectHolderRef
{
2018-09-06 11:39:01 +00:00
private static final Logger LOGGER = LogManager . getLogger ( ) ;
2014-05-25 02:32:24 +00:00
private Field field ;
2015-11-28 08:01:31 +00:00
private ResourceLocation injectedObject ;
2016-10-09 20:34:38 +00:00
private boolean isValid ;
2017-06-19 22:02:18 +00:00
private ForgeRegistry < ? > registry ;
2014-05-25 02:32:24 +00:00
2017-06-19 22:02:18 +00:00
ObjectHolderRef ( Field field , ResourceLocation injectedObject , boolean extractFromExistingValues )
2014-05-25 02:32:24 +00:00
{
2016-10-09 20:34:38 +00:00
registry = getRegistryForType ( field ) ;
2014-05-25 02:32:24 +00:00
this . field = field ;
2016-10-09 20:34:38 +00:00
this . isValid = registry ! = null ;
2014-05-25 02:32:24 +00:00
if ( extractFromExistingValues )
{
try
{
Object existing = field . get ( null ) ;
2014-05-26 14:58:13 +00:00
// nothing is ever allowed to replace AIR
2017-06-19 22:02:18 +00:00
if ( existing = = null | | existing = = registry . getDefault ( ) )
2014-05-26 14:58:13 +00:00
{
this . injectedObject = null ;
this . field = null ;
2016-10-09 20:34:38 +00:00
this . isValid = false ;
2014-05-26 14:58:13 +00:00
return ;
}
else
{
2018-09-06 11:39:01 +00:00
this . injectedObject = ( ( IForgeRegistryEntry ) existing ) . getRegistryName ( ) ;
2014-05-26 14:58:13 +00:00
}
2017-06-19 22:02:18 +00:00
}
2017-07-13 04:50:28 +00:00
catch ( IllegalAccessException e )
2014-05-25 02:32:24 +00:00
{
2017-06-19 22:02:18 +00:00
throw new RuntimeException ( e ) ;
2014-05-25 02:32:24 +00:00
}
}
else
{
this . injectedObject = injectedObject ;
}
if ( this . injectedObject = = null | | ! isValid ( ) )
{
2016-10-09 20:34:38 +00:00
throw new IllegalStateException ( String . format ( " The ObjectHolder annotation cannot apply to a field that does not map to a registry. Ensure the registry was created during the RegistryEvent.NewRegistry event. (found : %s at %s.%s) " , field . getType ( ) . getName ( ) , field . getClass ( ) . getName ( ) , field . getName ( ) ) ) ;
2014-05-25 02:32:24 +00:00
}
2018-09-06 11:39:01 +00:00
field . setAccessible ( true ) ;
if ( Modifier . isFinal ( field . getModifiers ( ) ) )
2014-05-25 02:32:24 +00:00
{
2018-09-06 11:39:01 +00:00
throw new RuntimeException ( " @ObjectHolder on final field, our transformer did not run? " + field . getDeclaringClass ( ) . getName ( ) + " / " + field . getName ( ) ) ;
2014-05-25 02:32:24 +00:00
}
}
2017-06-19 22:02:18 +00:00
@SuppressWarnings ( " unchecked " )
@Nullable
private ForgeRegistry < ? > getRegistryForType ( Field field )
2016-10-09 20:34:38 +00:00
{
Queue < Class < ? > > typesToExamine = new LinkedList < Class < ? > > ( ) ;
typesToExamine . add ( field . getType ( ) ) ;
2017-06-19 22:02:18 +00:00
ForgeRegistry < ? > registry = null ;
2016-10-09 22:57:18 +00:00
while ( ! typesToExamine . isEmpty ( ) & & registry = = null )
{
2016-10-09 20:34:38 +00:00
Class < ? > type = typesToExamine . remove ( ) ;
Collections . addAll ( typesToExamine , type . getInterfaces ( ) ) ;
2018-08-30 01:30:15 +00:00
if ( ForgeRegistryEntry . class . isAssignableFrom ( type ) )
2016-10-09 20:34:38 +00:00
{
2018-08-30 01:30:15 +00:00
registry = ( ForgeRegistry < ? > ) RegistryManager . ACTIVE . getRegistry ( ( Class < ForgeRegistryEntry > ) type ) ;
2016-10-09 20:34:38 +00:00
final Class < ? > parentType = type . getSuperclass ( ) ;
if ( parentType ! = null )
{
typesToExamine . add ( parentType ) ;
}
}
}
return registry ;
}
2014-05-25 02:32:24 +00:00
public boolean isValid ( )
{
2016-10-09 20:34:38 +00:00
return isValid ;
2014-05-25 02:32:24 +00:00
}
2017-06-19 22:02:18 +00:00
2014-05-25 02:32:24 +00:00
public void apply ( )
{
Object thing ;
2016-10-09 22:57:18 +00:00
if ( isValid & & registry . containsKey ( injectedObject ) & & ! registry . isDummied ( injectedObject ) )
2014-05-26 14:58:13 +00:00
{
2016-10-09 20:34:38 +00:00
thing = registry . getValue ( injectedObject ) ;
2014-05-26 14:58:13 +00:00
}
else
{
thing = null ;
}
if ( thing = = null )
{
2018-09-06 11:39:01 +00:00
LOGGER . 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
{
2018-09-06 11:39:01 +00:00
field . set ( null , thing ) ;
2014-05-25 02:32:24 +00:00
}
2017-07-13 04:50:28 +00:00
catch ( IllegalArgumentException | ReflectiveOperationException e )
2014-05-25 02:32:24 +00:00
{
2018-09-06 11:39:01 +00:00
LOGGER . warn ( " Unable to set {} with value {} ({}) " , this . field , thing , this . injectedObject , e ) ;
2017-06-19 22:02:18 +00:00
}
}
2014-05-25 02:32:24 +00:00
}