2018-07-01 14:17:28 -07:00
/*
* Minecraft Forge
* Copyright (c) 2016-2018.
*
* 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 15:02:18 -07:00
package net.minecraftforge.registries ;
import java.util.Map ;
import java.util.Set ;
import javax.annotation.Nullable ;
import com.google.common.collect.BiMap ;
import com.google.common.collect.HashBiMap ;
import com.google.common.collect.Maps ;
import com.google.common.collect.Sets ;
import com.google.common.collect.Sets.SetView ;
import net.minecraft.util.ResourceLocation ;
import net.minecraftforge.registries.ForgeRegistry.Snapshot ;
import net.minecraftforge.registries.IForgeRegistry.* ;
2018-08-29 21:30:15 -04:00
import org.apache.logging.log4j.LogManager ;
import org.apache.logging.log4j.Logger ;
2017-06-19 15:02:18 -07:00
public class RegistryManager
{
2018-08-29 21:30:15 -04:00
private static final Logger LOGGER = LogManager . getLogger ();
2017-06-19 15:02:18 -07:00
public static final RegistryManager ACTIVE = new RegistryManager ( "ACTIVE" );
public static final RegistryManager VANILLA = new RegistryManager ( "VANILLA" );
public static final RegistryManager FROZEN = new RegistryManager ( "FROZEN" );
BiMap < ResourceLocation , ForgeRegistry <? extends IForgeRegistryEntry <?>>> registries = HashBiMap . create ();
2018-08-29 21:30:15 -04:00
private BiMap < Class <? extends ForgeRegistryEntry <?>> , ResourceLocation > superTypes = HashBiMap . create ();
2017-06-19 15:02:18 -07:00
private Set < ResourceLocation > persisted = Sets . newHashSet ();
private final String name ;
public RegistryManager ( String name )
{
this . name = name ;
}
public String getName ()
{
return this . name ;
}
@SuppressWarnings ( "unchecked" )
public < V extends IForgeRegistryEntry < V >> Class < V > getSuperType ( ResourceLocation key )
{
return ( Class < V > ) superTypes . inverse (). get ( key );
}
@SuppressWarnings ( "unchecked" )
public < V extends IForgeRegistryEntry < V >> ForgeRegistry < V > getRegistry ( ResourceLocation key )
{
return ( ForgeRegistry < V > ) this . registries . get ( key );
}
public < V extends IForgeRegistryEntry < V >> IForgeRegistry < V > getRegistry ( Class < V > cls )
{
return getRegistry ( superTypes . get ( cls ));
}
public < V extends IForgeRegistryEntry < V >> ResourceLocation getName ( IForgeRegistry < V > reg )
{
return this . registries . inverse (). get ( reg );
}
public < V extends IForgeRegistryEntry < V >> ForgeRegistry < V > getRegistry ( ResourceLocation key , RegistryManager other )
{
if ( ! this . registries . containsKey ( key ))
{
ForgeRegistry < V > ot = other . getRegistry ( key );
if ( ot == null )
return null ;
this . registries . put ( key , ot . copy ( this ));
this . superTypes . put ( ot . getRegistrySuperType (), key );
if ( other . persisted . contains ( key ))
this . persisted . add ( key );
}
return getRegistry ( key );
}
< V extends IForgeRegistryEntry < V >> ForgeRegistry < V > createRegistry ( ResourceLocation name , Class < V > type , ResourceLocation defaultKey , int min , int max ,
2018-06-27 06:00:53 +01:00
@Nullable AddCallback < V > add , @Nullable ClearCallback < V > clear , @Nullable CreateCallback < V > create , @Nullable ValidateCallback < V > validate ,
2017-08-15 05:10:07 -07:00
boolean persisted , boolean allowOverrides , boolean isModifiable , @Nullable DummyFactory < V > dummyFactory , @Nullable MissingFactory < V > missing )
2017-06-19 15:02:18 -07:00
{
Set < Class <?>> parents = Sets . newHashSet ();
findSuperTypes ( type , parents );
SetView < Class <?>> overlappedTypes = Sets . intersection ( parents , superTypes . keySet ());
if ( ! overlappedTypes . isEmpty ())
{
Class <?> foundType = overlappedTypes . iterator (). next ();
2018-08-29 21:30:15 -04:00
LOGGER . error ( "Found existing registry of type {} named {}, you cannot create a new registry ({}) with type {}, as {} has a parent of that type" , foundType , superTypes . get ( foundType ), name , type , type );
2017-06-19 15:02:18 -07:00
throw new IllegalArgumentException ( "Duplicate registry parent type found - you can only have one registry for a particular super type" );
}
2018-06-27 06:00:53 +01:00
ForgeRegistry < V > reg = new ForgeRegistry < V > ( type , defaultKey , min , max , create , add , clear , validate , this , allowOverrides , isModifiable , dummyFactory , missing );
2017-06-19 15:02:18 -07:00
registries . put ( name , reg );
superTypes . put ( type , name );
if ( persisted )
this . persisted . add ( name );
return getRegistry ( name );
}
private void findSuperTypes ( Class <?> type , Set < Class <?>> types )
{
if ( type == null || type == Object . class )
{
return ;
}
types . add ( type );
for ( Class <?> interfac : type . getInterfaces ())
{
findSuperTypes ( interfac , types );
}
findSuperTypes ( type . getSuperclass (), types );
}
public Map < ResourceLocation , Snapshot > takeSnapshot ( boolean savingToDisc )
{
Map < ResourceLocation , Snapshot > ret = Maps . newHashMap ();
Set < ResourceLocation > keys = savingToDisc ? this . persisted : this . registries . keySet ();
keys . forEach ( name -> ret . put ( name , getRegistry ( name ). makeSnapshot ()));
return ret ;
}
//Public for testing only
public void clean ()
{
this . persisted . clear ();
this . registries . clear ();
this . superTypes . clear ();
}
}