2014-09-23 05:01:24 +00:00
package net.minecraftforge.fml.common.registry ;
2013-12-09 06:22:24 +00:00
import java.util.ArrayList ;
import java.util.BitSet ;
2014-03-20 11:41:59 +00:00
import java.util.Collections ;
import java.util.HashMap ;
2013-12-10 02:36:49 +00:00
import java.util.List ;
2013-12-09 06:22:24 +00:00
import java.util.Map ;
2014-04-30 22:24:58 +00:00
import java.util.Set ;
2014-04-01 05:00:20 +00:00
2014-09-20 00:24:36 +00:00
import org.apache.commons.lang3.Validate ;
2014-04-30 22:24:58 +00:00
import net.minecraft.block.Block ;
import net.minecraft.item.ItemBlock ;
2013-12-10 02:36:49 +00:00
import net.minecraft.util.ObjectIntIdentityMap ;
import net.minecraft.util.RegistryNamespaced ;
2014-09-20 00:24:36 +00:00
import net.minecraft.util.RegistryNamespacedDefaultedByKey ;
import net.minecraft.util.ResourceLocation ;
2014-09-23 05:01:24 +00:00
import net.minecraftforge.fml.common.FMLLog ;
import net.minecraftforge.fml.common.functions.GenericIterableFactory ;
2014-03-20 11:41:59 +00:00
2014-08-01 23:36:18 +00:00
import com.google.common.collect.BiMap ;
import com.google.common.collect.HashBiMap ;
2014-03-24 23:36:37 +00:00
import com.google.common.collect.ImmutableMap ;
2014-04-01 05:00:20 +00:00
2014-09-20 00:24:36 +00:00
public class FMLControlledNamespacedRegistry < I > extends RegistryNamespacedDefaultedByKey {
2013-12-09 06:22:24 +00:00
private final Class < I > superType ;
2014-09-20 00:24:36 +00:00
private Object optionalDefaultKey ;
2013-12-09 06:22:24 +00:00
private I optionalDefaultObject ;
2014-03-24 23:36:37 +00:00
private int maxId ;
2013-12-09 06:22:24 +00:00
private int minId ;
2013-12-10 02:36:49 +00:00
private char discriminator ;
2014-03-27 07:30:55 +00:00
// aliases redirecting legacy names to the actual name, may need recursive application to find the final name.
// these need to be registry specific, it's possible to only have a loosely linked item for a block which may get renamed by itself.
2014-03-24 23:36:37 +00:00
private final Map < String , String > aliases = new HashMap < String , String > ( ) ;
2014-08-20 14:28:39 +00:00
private BiMap < String , I > persistentSubstitutions ;
private BiMap < String , I > activeSubstitutions = HashBiMap . create ( ) ;
2013-12-09 06:22:24 +00:00
2014-09-20 00:24:36 +00:00
FMLControlledNamespacedRegistry ( Object defaultKey , int maxIdValue , int minIdValue , Class < I > type , char discriminator )
2013-12-09 06:22:24 +00:00
{
2014-09-20 00:24:36 +00:00
super ( defaultKey ) ;
2013-12-09 06:22:24 +00:00
this . superType = type ;
2013-12-10 02:36:49 +00:00
this . discriminator = discriminator ;
2014-09-20 00:24:36 +00:00
this . optionalDefaultKey = defaultKey ;
2013-12-09 06:22:24 +00:00
this . maxId = maxIdValue ;
this . minId = minIdValue ;
}
2014-04-30 22:24:58 +00:00
void validateContent ( int maxId , String type , BitSet availabilityMap , Set < Integer > blockedIds , FMLControlledNamespacedRegistry < Block > iBlockRegistry )
{
for ( I obj : typeSafeIterable ( ) )
{
int id = getId ( obj ) ;
2014-09-20 00:24:36 +00:00
Object name = func_177774_c ( obj ) ;
// name lookup failed -> obj is not in the obj<->name map
if ( name = = null ) throw new IllegalStateException ( String . format ( " Registry entry for %s %s, id %d, doesn't yield a name. " , type , obj , id ) ) ;
ResourceLocation loc = ( name instanceof ResourceLocation ) ? ( ResourceLocation ) name : null ;
String nameS = ( name instanceof String ) ? ( String ) name : ( loc ! = null ? name . toString ( ) : null ) ;
if ( loc = = null & & nameS = = null ) throw new IllegalStateException ( String . format ( " Registry entry for %s %s name is invalid, must be a String or ResourceLocation %s " , type , obj , name ) ) ;
2014-04-30 22:24:58 +00:00
// id lookup failed -> obj is not in the obj<->id map
if ( id < 0 ) throw new IllegalStateException ( String . format ( " Registry entry for %s %s, name %s, doesn't yield an id. " , type , obj , name ) ) ;
// id is too high
if ( id > maxId ) throw new IllegalStateException ( String . format ( " Registry entry for %s %s, name %s uses the too large id %d. " , type , obj , name ) ) ;
// empty name
2014-09-20 00:24:36 +00:00
if ( name . toString ( ) . isEmpty ( ) ) throw new IllegalStateException ( String . format ( " Registry entry for %s %s, id %d, yields an empty name. " , type , obj , id ) ) ;
2014-04-30 22:24:58 +00:00
// non-prefixed name
2014-09-20 00:24:36 +00:00
if ( name . toString ( ) . indexOf ( ':' ) = = - 1 ) throw new IllegalStateException ( String . format ( " Registry entry for %s %s, id %d, has the non-prefixed name %s. " , type , obj , id , name ) ) ;
2014-04-30 22:24:58 +00:00
// id -> obj lookup is inconsistent
if ( getRaw ( id ) ! = obj ) throw new IllegalStateException ( String . format ( " Registry entry for id %d, name %s, doesn't yield the expected %s %s. " , id , name , type , obj ) ) ;
// name -> obj lookup is inconsistent
2014-09-20 00:24:36 +00:00
if ( ! ( activeSubstitutions . containsKey ( name ) | | activeSubstitutions . containsValue ( name ) ) & & getRaw ( nameS ) ! = obj ) throw new IllegalStateException ( String . format ( " Registry entry for name %s, id %d, doesn't yield the expected %s %s. " , name , id , type , obj ) ) ;
2014-04-30 22:24:58 +00:00
// name -> id lookup is inconsistent
2014-09-20 00:24:36 +00:00
if ( ! ( activeSubstitutions . containsKey ( name ) | | activeSubstitutions . containsValue ( name ) ) & & getId ( nameS ) ! = id ) throw new IllegalStateException ( String . format ( " Registry entry for name %s doesn't yield the expected id %d. " , name , id ) ) ;
2014-04-30 22:24:58 +00:00
// id isn't marked as unavailable
if ( ! availabilityMap . get ( id ) ) throw new IllegalStateException ( String . format ( " Registry entry for %s %s, id %d, name %s, marked as empty. " , type , obj , id , name ) ) ;
// entry is blocked, thus should be empty
if ( blockedIds . contains ( id ) ) throw new IllegalStateException ( String . format ( " Registry entry for %s %s, id %d, name %s, marked as dangling. " , type , obj , id , name ) ) ;
if ( obj instanceof ItemBlock )
{
2014-09-20 00:24:36 +00:00
Block block = ( ( ItemBlock ) obj ) . blockInstance ;
2014-04-30 22:24:58 +00:00
// verify matching block entry
if ( iBlockRegistry . getId ( block ) ! = id )
{
throw new IllegalStateException ( String . format ( " Registry entry for ItemBlock %s, id %d, is missing or uses the non-matching id %d. " , obj , id , iBlockRegistry . getId ( block ) ) ) ;
}
// verify id range
if ( id > GameData . MAX_BLOCK_ID ) throw new IllegalStateException ( String . format ( " ItemBlock %s uses the id %d outside the block id range " , name , id ) ) ;
}
}
}
2014-03-20 11:41:59 +00:00
void set ( FMLControlledNamespacedRegistry < I > registry )
2013-12-09 06:22:24 +00:00
{
2014-03-20 11:41:59 +00:00
if ( this . superType ! = registry . superType ) throw new IllegalArgumentException ( " incompatible registry " ) ;
2013-12-09 06:22:24 +00:00
2014-03-20 11:41:59 +00:00
this . discriminator = registry . discriminator ;
2014-09-20 00:24:36 +00:00
this . optionalDefaultKey = registry . optionalDefaultKey ;
2014-03-20 11:41:59 +00:00
this . maxId = registry . maxId ;
this . minId = registry . minId ;
2014-03-27 07:30:55 +00:00
this . aliases . clear ( ) ;
2014-03-24 23:36:37 +00:00
this . aliases . putAll ( registry . aliases ) ;
2014-04-01 05:00:20 +00:00
underlyingIntegerMap = new ObjectIntIdentityMap ( ) ;
registryObjects . clear ( ) ;
2013-12-26 17:41:49 +00:00
2014-04-22 23:49:07 +00:00
for ( I thing : registry . typeSafeIterable ( ) )
2013-12-26 17:41:49 +00:00
{
2014-09-20 00:24:36 +00:00
addObjectRaw ( registry . getId ( thing ) , registry . func_177774_c ( thing ) , thing ) ;
2013-12-26 17:41:49 +00:00
}
2014-03-20 11:41:59 +00:00
}
2013-12-26 17:41:49 +00:00
2014-03-24 23:36:37 +00:00
// public api
2014-03-20 11:41:59 +00:00
/ * *
* Add an object to the registry , trying to use the specified id .
*
* @deprecated register through { @link GameRegistry } instead .
* /
@Override
@Deprecated
2014-09-20 00:24:36 +00:00
public void func_177775_a ( int id , Object name , Object thing )
2014-03-20 11:41:59 +00:00
{
2014-09-20 00:24:36 +00:00
Validate . isInstanceOf ( ResourceLocation . class , name ) ;
GameData . getMain ( ) . register ( thing , name . toString ( ) , id ) ;
2013-12-24 05:47:10 +00:00
}
2014-03-20 11:41:59 +00:00
2014-04-06 15:11:23 +00:00
/ * *
* DANGEROUS ! EVIL ! DO NOT USE !
*
* @deprecated register through { @link GameRegistry } instead .
* /
@Override
@Deprecated
public void putObject ( Object objName , Object obj )
{
2014-09-20 00:24:36 +00:00
String name = objName . toString ( ) ;
2014-04-22 23:49:07 +00:00
I thing = superType . cast ( obj ) ;
2014-04-06 15:11:23 +00:00
if ( name = = null ) throw new NullPointerException ( " Can't use a null-name for the registry. " ) ;
if ( name . isEmpty ( ) ) throw new IllegalArgumentException ( " Can't use an empty name for the registry. " ) ;
if ( thing = = null ) throw new NullPointerException ( " Can't add null-object to the registry. " ) ;
2014-09-20 00:24:36 +00:00
name = new ResourceLocation ( name ) . toString ( ) ;
Object existingName = func_177774_c ( thing ) ;
2014-04-06 15:11:23 +00:00
if ( existingName = = null )
{
FMLLog . bigWarning ( " Ignoring putObject(%s, %s), not resolvable " , name , thing ) ;
}
else if ( existingName . equals ( name ) )
{
FMLLog . bigWarning ( " Ignoring putObject(%s, %s), already added " , name , thing ) ;
}
else
{
FMLLog . bigWarning ( " Ignoring putObject(%s, %s), adding alias to %s instead " , name , thing , existingName ) ;
2014-09-20 00:24:36 +00:00
addAlias ( name , existingName . toString ( ) ) ;
2014-04-06 15:11:23 +00:00
}
}
2014-04-07 15:30:38 +00:00
/ * *
* Fetch the object identified by the specified name or the default object .
*
* For blocks the default object is the air block , for items it ' s null .
*
* @param name Unique name identifying the object .
* @return Registered object of the default object if it wasn ' t found -
* /
2013-12-09 06:22:24 +00:00
@Override
2014-09-20 00:24:36 +00:00
public I getObject ( Object name )
2013-12-09 06:22:24 +00:00
{
2014-09-20 00:24:36 +00:00
I object = null ;
if ( name instanceof ResourceLocation ) object = getRaw ( ( ResourceLocation ) name ) ;
if ( name instanceof String ) object = getRaw ( ( String ) name ) ;
2013-12-09 06:22:24 +00:00
return object = = null ? this . optionalDefaultObject : object ;
}
2014-04-07 15:30:38 +00:00
/ * *
* Fetch the object identified by the specified id or the default object .
*
* For blocks the default object is the air block , for items it ' s null .
*
* @param id ID identifying the object .
* @return Registered object of the default object if it wasn ' t found -
* /
2013-12-09 06:22:24 +00:00
@Override
2014-03-19 07:15:53 +00:00
public I getObjectById ( int id )
2013-12-09 06:22:24 +00:00
{
2014-03-24 23:36:37 +00:00
I object = getRaw ( id ) ;
2013-12-09 06:22:24 +00:00
return object = = null ? this . optionalDefaultObject : object ;
}
2014-03-24 23:36:37 +00:00
/ * *
2014-04-01 05:00:20 +00:00
* @deprecated use getObjectById instead
2014-03-24 23:36:37 +00:00
* /
2014-04-01 05:00:20 +00:00
@Deprecated
2014-03-24 23:36:37 +00:00
public I get ( int id )
{
2014-04-01 05:00:20 +00:00
return getObjectById ( id ) ;
2014-03-24 23:36:37 +00:00
}
/ * *
2014-04-01 05:00:20 +00:00
* @deprecated use getObject instead
2014-03-24 23:36:37 +00:00
* /
2014-04-01 05:00:20 +00:00
@Deprecated
2014-03-24 23:36:37 +00:00
public I get ( String name )
{
2014-04-01 05:00:20 +00:00
return getObject ( name ) ;
2014-03-24 23:36:37 +00:00
}
2013-12-09 06:22:24 +00:00
2014-03-24 23:36:37 +00:00
/ * *
* Get the id for the specified object .
*
* Don ' t hold onto the id across the world , it ' s being dynamically re - mapped as needed .
*
* Usually the name should be used instead of the id , if using the Block / Item object itself is
* not suitable for the task .
*
2014-03-27 07:30:55 +00:00
* @param thing Block / Item object .
2014-03-24 23:36:37 +00:00
* @return Block / Item id or - 1 if it wasn ' t found .
* /
public int getId ( I thing )
2013-12-09 06:22:24 +00:00
{
2014-04-01 05:00:20 +00:00
return getIDForObject ( thing ) ;
2013-12-10 02:36:49 +00:00
}
2014-03-24 23:36:37 +00:00
/ * *
* Get the object identified by the specified id .
*
* @param id Block / Item id .
* @return Block / Item object or null if it wasn ' t found .
* /
public I getRaw ( int id )
2013-12-10 02:36:49 +00:00
{
2014-04-01 05:00:20 +00:00
return superType . cast ( super . getObjectById ( id ) ) ;
2013-12-10 02:36:49 +00:00
}
2013-12-09 06:22:24 +00:00
2014-03-24 23:36:37 +00:00
/ * *
* Get the object identified by the specified name .
*
* @param name Block / Item name .
* @return Block / Item object or null if it wasn ' t found .
* /
public I getRaw ( String name )
2013-12-10 02:36:49 +00:00
{
2014-09-20 00:24:36 +00:00
return getRaw ( new ResourceLocation ( name ) ) ;
}
/ * *
* Get the object identified by the specified name .
*
* @param name Block / Item name .
* @return Block / Item object or null if it wasn ' t found .
* /
private I getRaw ( ResourceLocation loc )
{
I ret = superType . cast ( super . getObject ( loc ) ) ;
2013-12-10 02:36:49 +00:00
2014-03-24 23:36:37 +00:00
if ( ret = = null ) // no match, try aliases recursively
2013-12-24 05:47:10 +00:00
{
2014-09-20 00:24:36 +00:00
String name = aliases . get ( loc . toString ( ) ) ;
2014-03-24 23:36:37 +00:00
if ( name ! = null ) return getRaw ( name ) ;
2013-12-24 05:47:10 +00:00
}
2013-12-09 06:22:24 +00:00
2014-03-20 11:41:59 +00:00
return ret ;
2013-12-18 16:15:03 +00:00
}
2014-04-07 15:30:38 +00:00
/ * *
* Determine if the registry has an entry for the specified name .
*
* Aliased names will be resolved as well .
*
* @param name Object name to check .
* @return true if a matching entry was found .
* /
2014-03-24 23:36:37 +00:00
@Override
2014-09-20 00:24:36 +00:00
public boolean containsKey ( Object name )
2013-12-09 06:22:24 +00:00
{
2014-04-01 05:00:20 +00:00
boolean ret = super . containsKey ( name ) ;
2013-12-09 06:22:24 +00:00
2014-03-24 23:36:37 +00:00
if ( ! ret ) // no match, try aliases recursively
{
name = aliases . get ( name ) ;
2013-12-09 06:22:24 +00:00
2014-04-01 05:00:20 +00:00
if ( name ! = null ) return containsKey ( name ) ;
2014-03-24 23:36:37 +00:00
}
return ret ;
2013-12-09 06:22:24 +00:00
}
2013-12-10 02:36:49 +00:00
2014-03-27 07:30:55 +00:00
/ * *
* Get the id for the specified object .
*
* Don ' t hold onto the id across the world , it ' s being dynamically re - mapped as needed .
*
* Usually the name should be used instead of the id , if using the Block / Item object itself is
* not suitable for the task .
*
* @param itemName Block / Item registry name .
* @return Block / Item id or - 1 if it wasn ' t found .
* /
2014-03-24 23:36:37 +00:00
public int getId ( String itemName )
2013-12-09 06:22:24 +00:00
{
2014-03-24 23:36:37 +00:00
I obj = getRaw ( itemName ) ;
if ( obj = = null ) return - 1 ;
return getId ( obj ) ;
2013-12-09 06:22:24 +00:00
}
2013-12-10 02:36:49 +00:00
2014-04-01 05:00:20 +00:00
/ * *
* @deprecated use containsKey instead
* /
@Deprecated
2014-03-24 23:36:37 +00:00
public boolean contains ( String itemName )
2013-12-10 02:36:49 +00:00
{
2014-04-01 05:00:20 +00:00
return containsKey ( itemName ) ;
2013-12-10 02:36:49 +00:00
}
2014-04-22 23:49:07 +00:00
public Iterable < I > typeSafeIterable ( )
{
2014-04-30 22:24:58 +00:00
Iterable < ? > self = this ;
return GenericIterableFactory . newCastingIterable ( self , superType ) ;
2014-04-22 23:49:07 +00:00
}
2014-03-24 23:36:37 +00:00
// internal
2014-04-07 15:30:38 +00:00
public void serializeInto ( Map < String , Integer > idMapping ) // for saving
2013-12-10 02:36:49 +00:00
{
2014-04-22 23:49:07 +00:00
for ( I thing : this . typeSafeIterable ( ) )
2014-03-20 11:41:59 +00:00
{
2014-09-20 00:24:36 +00:00
idMapping . put ( discriminator + func_177774_c ( thing ) . toString ( ) , getId ( thing ) ) ;
2014-03-20 11:41:59 +00:00
}
2013-12-10 02:36:49 +00:00
}
2014-04-07 15:30:38 +00:00
public Map < String , String > getAliases ( ) // for saving
2013-12-10 02:36:49 +00:00
{
2014-03-24 23:36:37 +00:00
return ImmutableMap . copyOf ( aliases ) ;
}
2014-03-20 11:41:59 +00:00
2014-04-07 15:30:38 +00:00
/ * *
* Add the specified object to the registry .
*
* @param id ID to use if available , auto - assigned otherwise .
* @param name Name to use , prefixed by the mod id .
* @param thing Object to add .
* @param availabilityMap Map marking available IDs for auto assignment .
* @return ID eventually allocated .
* /
2014-03-24 23:36:37 +00:00
int add ( int id , String name , I thing , BitSet availabilityMap )
{
2014-04-22 23:49:07 +00:00
if ( name = = null ) throw new NullPointerException ( String . format ( " Can't use a null-name for the registry, object %s. " , thing ) ) ;
if ( name . isEmpty ( ) ) throw new IllegalArgumentException ( String . format ( " Can't use an empty name for the registry, object %s. " , thing ) ) ;
if ( name . indexOf ( ':' ) = = - 1 ) throw new IllegalArgumentException ( String . format ( " Can't add the name (%s) without a prefix, object %s " , name , thing ) ) ;
if ( thing = = null ) throw new NullPointerException ( String . format ( " Can't add null-object to the registry, name %s. " , name ) ) ;
2014-09-20 00:24:36 +00:00
if ( optionalDefaultKey ! = null & & optionalDefaultKey . toString ( ) . equals ( name ) & & this . optionalDefaultObject = = null )
2014-03-24 23:36:37 +00:00
{
this . optionalDefaultObject = thing ;
}
2014-08-20 14:28:39 +00:00
if ( getPersistentSubstitutions ( ) . containsValue ( thing ) )
{
throw new IllegalArgumentException ( String . format ( " The object %s (%s) cannot be added to the registry. It is already being used as a substitute for %s " , thing . getClass ( ) , name , getPersistentSubstitutions ( ) . inverse ( ) . get ( thing ) ) ) ;
}
2014-03-24 23:36:37 +00:00
int idToUse = id ;
2014-04-09 20:21:04 +00:00
if ( idToUse < 0 | | availabilityMap . get ( idToUse ) )
2014-03-24 23:36:37 +00:00
{
idToUse = availabilityMap . nextClearBit ( minId ) ;
}
2014-04-07 15:30:38 +00:00
if ( idToUse > maxId )
2014-03-24 23:36:37 +00:00
{
2014-04-09 20:21:04 +00:00
throw new RuntimeException ( String . format ( " Invalid id %d - maximum id range exceeded. " , idToUse ) ) ;
2014-03-24 23:36:37 +00:00
}
2014-04-06 15:11:23 +00:00
if ( getRaw ( name ) = = thing ) // already registered, return prev registration's id
{
FMLLog . bigWarning ( " The object %s has been registered twice for the same name %s. " , thing , name ) ;
return getId ( thing ) ;
}
2014-04-11 04:33:36 +00:00
if ( getRaw ( name ) ! = null ) // duplicate name
2014-04-01 12:40:24 +00:00
{
2014-04-11 04:33:36 +00:00
throw new IllegalArgumentException ( String . format ( " The name %s has been registered twice, for %s and %s. " , name , getRaw ( name ) , thing ) ) ;
2014-04-01 12:40:24 +00:00
}
2014-08-20 14:28:39 +00:00
if ( getId ( thing ) > = 0 ) // duplicate object - but only if it's not being substituted
2014-04-01 12:40:24 +00:00
{
2014-05-10 18:53:08 +00:00
int foundId = getId ( thing ) ;
Object otherThing = getRaw ( foundId ) ;
2014-09-20 00:24:36 +00:00
throw new IllegalArgumentException ( String . format ( " The object %s{%x} has been registered twice, using the names %s and %s. (Other object at this id is %s{%x}) " , thing , System . identityHashCode ( thing ) , func_177774_c ( thing ) , name , otherThing , System . identityHashCode ( otherThing ) ) ) ;
2014-04-01 12:40:24 +00:00
}
2014-04-06 12:49:59 +00:00
if ( GameData . isFrozen ( this ) )
{
2014-04-06 15:11:23 +00:00
FMLLog . bigWarning ( " The object %s (name %s) is being added too late. " , thing , name ) ;
2014-04-06 12:49:59 +00:00
}
2014-04-01 12:40:24 +00:00
2014-08-20 14:28:39 +00:00
if ( activeSubstitutions . containsKey ( name ) )
{
thing = activeSubstitutions . get ( name ) ;
}
2014-09-20 00:24:36 +00:00
addObjectRaw ( idToUse , new ResourceLocation ( name ) , thing ) ;
2014-04-06 15:11:23 +00:00
2014-04-09 20:21:04 +00:00
FMLLog . finer ( " Registry add: %s %d %s (req. id %d) " , name , idToUse , thing , id ) ;
2014-03-24 23:36:37 +00:00
return idToUse ;
2013-12-10 02:36:49 +00:00
}
2014-03-24 23:36:37 +00:00
void addAlias ( String from , String to )
2013-12-10 02:36:49 +00:00
{
2014-03-24 23:36:37 +00:00
aliases . put ( from , to ) ;
2014-04-06 15:11:23 +00:00
FMLLog . finer ( " Registry alias: %s -> %s " , from , to ) ;
2014-03-24 23:36:37 +00:00
}
Map < String , Integer > getEntriesNotIn ( FMLControlledNamespacedRegistry < I > registry )
{
Map < String , Integer > ret = new HashMap < String , Integer > ( ) ;
2014-04-22 23:49:07 +00:00
for ( I thing : this . typeSafeIterable ( ) )
2014-03-24 23:36:37 +00:00
{
2014-08-20 14:28:39 +00:00
if ( ! registry . field_148758_b . containsKey ( thing ) )
{
2014-09-20 00:24:36 +00:00
if ( ! registry . activeSubstitutions . containsKey ( func_177774_c ( thing ) . toString ( ) ) )
2014-08-20 14:28:39 +00:00
{
2014-09-20 00:24:36 +00:00
ret . put ( func_177774_c ( thing ) . toString ( ) , getId ( thing ) ) ;
2014-08-20 14:28:39 +00:00
}
}
2014-03-24 23:36:37 +00:00
}
return ret ;
2013-12-10 02:36:49 +00:00
}
2013-12-26 17:41:49 +00:00
void dump ( )
{
2014-03-20 11:41:59 +00:00
List < Integer > ids = new ArrayList < Integer > ( ) ;
2014-04-22 23:49:07 +00:00
for ( I thing : this . typeSafeIterable ( ) )
2013-12-26 17:41:49 +00:00
{
2014-03-27 07:30:55 +00:00
ids . add ( getId ( thing ) ) ;
2014-03-20 11:41:59 +00:00
}
// sort by id
Collections . sort ( ids ) ;
for ( int id : ids )
{
I thing = getRaw ( id ) ;
2014-09-20 00:24:36 +00:00
FMLLog . finer ( " Registry: %s %d %s " , func_177774_c ( thing ) , id , thing ) ;
2013-12-26 17:41:49 +00:00
}
2014-02-01 11:05:33 +00:00
}
2014-04-06 15:11:23 +00:00
/ * *
* Version of addObject not using the API restricting overrides .
* /
2014-09-20 00:24:36 +00:00
private void addObjectRaw ( int id , Object name , I thing )
2014-04-06 15:11:23 +00:00
{
2014-04-22 23:49:07 +00:00
if ( name = = null ) throw new NullPointerException ( " The name to be added to the registry is null. This can only happen with a corrupted registry state. Reflection/ASM hackery? Registry bug? " ) ;
if ( thing = = null ) throw new NullPointerException ( " The object to be added to the registry is null. This can only happen with a corrupted registry state. Reflection/ASM hackery? Registry bug? " ) ;
if ( ! superType . isInstance ( thing ) ) throw new IllegalArgumentException ( " The object to be added to the registry is not of the right type. Reflection/ASM hackery? Registry bug? " ) ;
2014-04-06 15:11:23 +00:00
underlyingIntegerMap . func_148746_a ( thing , id ) ; // obj <-> id
2014-04-22 23:49:07 +00:00
super . putObject ( name , thing ) ; // name <-> obj
}
2014-05-26 14:58:13 +00:00
public I getDefaultValue ( )
{
return optionalDefaultObject ;
}
2014-07-30 23:48:31 +00:00
public RegistryDelegate < I > getDelegate ( I thing , Class < I > clazz ) {
return GameData . buildDelegate ( thing , clazz ) ;
}
2014-08-01 23:36:18 +00:00
2014-08-20 14:28:39 +00:00
void activateSubstitution ( String nameToReplace )
{
if ( getPersistentSubstitutions ( ) . containsKey ( nameToReplace ) )
{
activeSubstitutions . put ( nameToReplace , getPersistentSubstitutions ( ) . get ( nameToReplace ) ) ;
}
}
2014-08-21 02:46:39 +00:00
void addSubstitutionAlias ( String modId , String nameToReplace , Object toReplace ) throws ExistingSubstitutionException {
2014-08-20 14:28:39 +00:00
if ( getPersistentSubstitutions ( ) . containsKey ( nameToReplace ) | | getPersistentSubstitutions ( ) . containsValue ( toReplace ) )
{
FMLLog . severe ( " The substitution of %s has already occured. You cannot duplicate substitutions " , nameToReplace ) ;
throw new ExistingSubstitutionException ( nameToReplace , toReplace ) ;
}
I replacement = superType . cast ( toReplace ) ;
I original = getRaw ( nameToReplace ) ;
2014-08-21 02:46:39 +00:00
if ( original = = null )
{
throw new NullPointerException ( " The replacement target is not present. This won't work " ) ;
}
2014-08-20 14:28:39 +00:00
if ( ! original . getClass ( ) . isAssignableFrom ( replacement . getClass ( ) ) )
{
FMLLog . severe ( " The substitute %s for %s (type %s) is type incompatible. This won't work " , replacement . getClass ( ) . getName ( ) , nameToReplace , original . getClass ( ) . getName ( ) ) ;
throw new IncompatibleSubstitutionException ( nameToReplace , replacement , original ) ;
}
int existingId = getId ( replacement ) ;
if ( existingId ! = - 1 )
{
FMLLog . severe ( " The substitute %s for %s is registered into the game independently. This won't work " , replacement . getClass ( ) . getName ( ) , nameToReplace ) ;
throw new IllegalArgumentException ( " The object substitution is already registered. This won't work " ) ;
}
getPersistentSubstitutions ( ) . put ( nameToReplace , replacement ) ;
}
public void serializeSubstitutions ( Set < String > blockSubs )
{
blockSubs . addAll ( activeSubstitutions . keySet ( ) ) ;
}
private BiMap < String , I > getPersistentSubstitutions ( )
{
if ( persistentSubstitutions = = null )
2014-08-01 23:36:18 +00:00
{
2014-08-20 14:28:39 +00:00
persistentSubstitutions = GameData . getMain ( ) . getPersistentSubstitutionMap ( superType ) ;
2014-08-01 23:36:18 +00:00
}
2014-08-20 14:28:39 +00:00
return persistentSubstitutions ;
2014-08-01 23:36:18 +00:00
}
2014-09-20 00:24:36 +00:00
@Override
public void func_177776_a ( )
{
if ( this . optionalDefaultKey ! = null )
Validate . notNull ( this . optionalDefaultObject ) ;
}
2013-12-09 06:22:24 +00:00
}