2013-05-23 01:01:19 -04:00
package net.minecraftforge.fluids ;
import java.util.Map ;
2015-04-07 20:06:55 -07:00
import java.util.Map.Entry ;
2015-04-11 17:18:53 -04:00
import java.util.Set ;
import org.apache.logging.log4j.Level ;
2013-05-23 01:01:19 -04:00
import net.minecraft.block.Block ;
2015-06-18 14:14:46 +03:00
import net.minecraft.client.renderer.texture.TextureAtlasSprite ;
import net.minecraft.client.renderer.texture.TextureMap ;
2014-01-29 18:34:23 -08:00
import net.minecraft.init.Blocks ;
2015-04-11 17:18:53 -04:00
import net.minecraft.nbt.NBTTagCompound ;
import net.minecraft.nbt.NBTTagList ;
import net.minecraft.nbt.NBTTagString ;
2015-06-18 14:14:46 +03:00
import net.minecraft.util.ResourceLocation ;
2013-11-12 01:05:13 -08:00
import net.minecraft.util.StatCollector ;
2013-05-23 01:01:19 -04:00
import net.minecraftforge.common.MinecraftForge ;
2015-04-18 21:37:45 -04:00
import com.google.common.base.Strings ;
2013-05-23 01:01:19 -04:00
import com.google.common.collect.BiMap ;
import com.google.common.collect.HashBiMap ;
import com.google.common.collect.ImmutableMap ;
2014-01-29 18:34:23 -08:00
import com.google.common.collect.Maps ;
2015-04-11 17:18:53 -04:00
import com.google.common.collect.Sets ;
2013-05-23 01:01:19 -04:00
2015-06-01 16:29:34 -04:00
import net.minecraftforge.fml.common.FMLLog ;
import net.minecraftforge.fml.common.Loader ;
import net.minecraftforge.fml.common.ModContainer ;
2014-11-25 19:56:35 -08:00
import net.minecraftforge.fml.common.eventhandler.Event ;
2015-06-01 16:29:34 -04:00
import net.minecraftforge.fml.common.registry.RegistryDelegate ;
2013-12-16 20:18:48 -05:00
2013-05-23 01:01:19 -04:00
/**
* Handles Fluid registrations. Fluids MUST be registered in order to function.
2013-07-27 23:36:27 +02:00
*
2013-05-23 01:01:19 -04:00
* @author King Lemming, CovertJaguar (LiquidDictionary)
2013-07-27 23:36:27 +02:00
*
2013-05-23 01:01:19 -04:00
*/
2013-07-16 21:40:49 -07:00
public abstract class FluidRegistry
{
2013-05-23 01:01:19 -04:00
static int maxID = 0 ;
2015-03-25 01:27:15 -04:00
static BiMap < String , Fluid > fluids = HashBiMap . create ();
static BiMap < Fluid , Integer > fluidIDs = HashBiMap . create ();
2015-04-07 20:06:55 -07:00
static BiMap < Integer , String > fluidNames = HashBiMap . create (); //Caching this just makes some other calls faster
2013-09-05 12:08:16 -04:00
static BiMap < Block , Fluid > fluidBlocks ;
2015-04-05 16:13:17 -04:00
2015-04-11 17:18:53 -04:00
// the globally unique fluid map - only used to associate non-defaults during world/server loading
static BiMap < String , Fluid > masterFluidReference = HashBiMap . create ();
static BiMap < String , String > defaultFluidName = HashBiMap . create ();
2015-04-20 09:26:27 -04:00
static Map < Fluid , FluidDelegate > delegates = Maps . newHashMap ();
2015-04-11 17:18:53 -04:00
2015-06-18 14:14:46 +03:00
public static final Fluid WATER = new Fluid ( "water" , new ResourceLocation ( "blocks/water_still" ), new ResourceLocation ( "blocks/water_flow" )) {
2013-11-12 01:05:13 -08:00
@Override
public String getLocalizedName () {
return StatCollector . translateToLocal ( "tile.water.name" );
}
2014-02-05 00:05:37 -08:00
}. setBlock ( Blocks . water ). setUnlocalizedName ( Blocks . water . getUnlocalizedName ());
2015-04-05 16:13:17 -04:00
2015-06-18 14:14:46 +03:00
public static final Fluid LAVA = new Fluid ( "lava" , new ResourceLocation ( "blocks/lava_still" ), new ResourceLocation ( "blocks/lava_flow" )) {
2013-11-12 01:05:13 -08:00
@Override
public String getLocalizedName () {
return StatCollector . translateToLocal ( "tile.lava.name" );
}
2014-02-05 00:05:37 -08:00
}. setBlock ( Blocks . lava ). setLuminosity ( 15 ). setDensity ( 3000 ). setViscosity ( 6000 ). setTemperature ( 1300 ). setUnlocalizedName ( Blocks . lava . getUnlocalizedName ());
2013-05-23 01:01:19 -04:00
public static int renderIdFluid = - 1 ;
2013-07-16 21:40:49 -07:00
static
{
2013-05-23 01:01:19 -04:00
registerFluid ( WATER );
registerFluid ( LAVA );
}
2013-07-16 21:40:49 -07:00
private FluidRegistry (){}
2013-05-23 01:01:19 -04:00
/**
* Called by Forge to prepare the ID map for server -> client sync.
2014-01-29 18:34:23 -08:00
* Modders, DO NOT call this.
*/
2015-04-11 17:18:53 -04:00
public static void initFluidIDs ( BiMap < Fluid , Integer > newfluidIDs , Set < String > defaultNames )
2013-07-16 21:40:49 -07:00
{
2013-05-23 01:01:19 -04:00
maxID = newfluidIDs . size ();
2015-06-03 19:26:53 -04:00
loadFluidDefaults ( newfluidIDs , defaultNames );
2013-05-23 01:01:19 -04:00
}
/**
2015-04-11 17:18:53 -04:00
* Called by forge to load default fluid IDs from the world or from server -> client for syncing
* DO NOT call this and expect useful behaviour.
2015-06-03 19:26:53 -04:00
* @param newfluidIDs
2015-04-11 17:18:53 -04:00
*/
2015-06-03 19:26:53 -04:00
private static void loadFluidDefaults ( BiMap < Fluid , Integer > localFluidIDs , Set < String > defaultNames )
2015-04-11 17:18:53 -04:00
{
// If there's an empty set of default names, use the defaults as defined locally
if ( defaultNames . isEmpty ()) {
defaultNames . addAll ( defaultFluidName . values ());
}
2015-06-03 19:26:53 -04:00
BiMap < String , Fluid > localFluids = HashBiMap . create ( fluids );
2015-04-11 17:18:53 -04:00
for ( String defaultName : defaultNames )
{
Fluid fluid = masterFluidReference . get ( defaultName );
if ( fluid == null ) {
String derivedName = defaultName . split ( ":" , 2 ) [ 1 ] ;
String localDefault = defaultFluidName . get ( derivedName );
if ( localDefault == null ) {
FMLLog . getLogger (). log ( Level . ERROR , "The fluid {} (specified as {}) is missing from this instance - it will be removed" , derivedName , defaultName );
continue ;
}
fluid = masterFluidReference . get ( localDefault );
FMLLog . getLogger (). log ( Level . ERROR , "The fluid {} specified as default is not present - it will be reverted to default {}" , defaultName , localDefault );
}
FMLLog . getLogger (). log ( Level . DEBUG , "The fluid {} has been selected as the default fluid for {}" , defaultName , fluid . getName ());
2015-06-03 19:26:53 -04:00
Fluid oldFluid = localFluids . put ( fluid . getName (), fluid );
Integer id = localFluidIDs . remove ( oldFluid );
localFluidIDs . put ( fluid , id );
}
BiMap < Integer , String > localFluidNames = fluidNames ;
for ( Entry < Fluid , Integer > e : localFluidIDs . entrySet ()) {
localFluidNames . put ( e . getValue (), e . getKey (). getName ());
2015-04-11 17:18:53 -04:00
}
2015-06-03 19:26:53 -04:00
fluidIDs = localFluidIDs ;
fluids = localFluids ;
fluidNames = localFluidNames ;
2015-04-11 17:18:53 -04:00
fluidBlocks = null ;
2015-04-20 09:06:23 -04:00
for ( FluidDelegate fd : delegates . values ())
{
fd . rebind ();
}
2013-05-23 01:01:19 -04:00
}
/**
2015-04-11 17:18:53 -04:00
* Register a new Fluid. If a fluid with the same name already exists, registration the alternative fluid is tracked
* in case it is the default in another place
2013-07-27 23:36:27 +02:00
*
2013-05-23 01:01:19 -04:00
* @param fluid
* The fluid to register.
2015-04-11 17:18:53 -04:00
* @return True if the fluid was registered as the current default fluid, false if it was only registered as an alternative
2014-01-29 18:34:23 -08:00
*/
2013-07-16 21:40:49 -07:00
public static boolean registerFluid ( Fluid fluid )
{
2015-04-11 17:18:53 -04:00
masterFluidReference . put ( uniqueName ( fluid ), fluid );
2015-04-20 09:06:23 -04:00
delegates . put ( fluid , new FluidDelegate ( fluid , fluid . getName ()));
2015-04-08 17:26:40 +06:00
if ( fluids . containsKey ( fluid . getName ()))
2013-07-16 21:40:49 -07:00
{
2013-05-23 01:01:19 -04:00
return false ;
}
fluids . put ( fluid . getName (), fluid );
2015-04-10 16:38:45 -04:00
maxID ++ ;
fluidIDs . put ( fluid , maxID );
2015-04-07 20:06:55 -07:00
fluidNames . put ( maxID , fluid . getName ());
2015-04-11 17:18:53 -04:00
defaultFluidName . put ( fluid . getName (), uniqueName ( fluid ));
2013-05-23 01:01:19 -04:00
MinecraftForge . EVENT_BUS . post ( new FluidRegisterEvent ( fluid . getName (), maxID ));
return true ;
}
2015-04-11 17:18:53 -04:00
private static String uniqueName ( Fluid fluid )
{
ModContainer activeModContainer = Loader . instance (). activeModContainer ();
String activeModContainerName = activeModContainer == null ? "minecraft" : activeModContainer . getModId ();
return activeModContainerName + ":" + fluid . getName ();
}
/**
* Is the supplied fluid the current default fluid for it's name
* @param fluid the fluid we're testing
* @return if the fluid is default
*/
public static boolean isFluidDefault ( Fluid fluid )
{
return fluids . containsValue ( fluid );
}
/**
* Does the supplied fluid have an entry for it's name (whether or not the fluid itself is default)
* @param fluid the fluid we're testing
* @return if the fluid's name has a registration entry
*/
2013-07-16 21:40:49 -07:00
public static boolean isFluidRegistered ( Fluid fluid )
{
2015-04-11 17:27:14 -04:00
return fluid != null && fluids . containsKey ( fluid . getName ());
2013-05-23 01:01:19 -04:00
}
2013-07-16 21:40:49 -07:00
public static boolean isFluidRegistered ( String fluidName )
{
2015-03-25 01:27:15 -04:00
return fluids . containsKey ( fluidName );
2013-05-23 01:01:19 -04:00
}
2013-07-16 21:40:49 -07:00
public static Fluid getFluid ( String fluidName )
{
2013-05-23 01:01:19 -04:00
return fluids . get ( fluidName );
}
2013-07-16 21:40:49 -07:00
public static Fluid getFluid ( int fluidID )
{
2015-06-03 19:26:53 -04:00
return fluidIDs . inverse (). get ( fluidID );
2013-05-23 01:01:19 -04:00
}
2015-03-25 01:27:15 -04:00
public static int getFluidID ( Fluid fluid )
2013-07-16 21:40:49 -07:00
{
2015-06-03 19:26:53 -04:00
return fluidIDs . get ( fluid );
2013-05-23 01:01:19 -04:00
}
2015-03-25 01:27:15 -04:00
public static int getFluidID ( String fluidName )
2013-07-16 21:40:49 -07:00
{
2015-06-03 19:26:53 -04:00
return fluidIDs . get ( getFluid ( fluidName ));
2013-05-23 01:01:19 -04:00
}
2015-04-07 20:06:55 -07:00
@Deprecated //Remove in 1.8.3
2013-07-16 21:40:49 -07:00
public static String getFluidName ( int fluidID )
{
2015-04-07 20:06:55 -07:00
return fluidNames . get ( fluidID );
2013-05-23 01:01:19 -04:00
}
2015-03-25 01:27:15 -04:00
public static String getFluidName ( Fluid fluid )
2013-07-16 21:40:49 -07:00
{
2015-03-25 01:27:15 -04:00
return fluids . inverse (). get ( fluid );
2013-05-23 01:01:19 -04:00
}
2015-03-25 01:27:15 -04:00
public static String getFluidName ( FluidStack stack )
2013-07-16 21:40:49 -07:00
{
2015-04-20 09:06:23 -04:00
return getFluidName ( stack . getFluid ());
2013-05-23 01:01:19 -04:00
}
2013-07-16 21:40:49 -07:00
public static FluidStack getFluidStack ( String fluidName , int amount )
{
2015-03-25 01:27:15 -04:00
if ( ! fluids . containsKey ( fluidName ))
2013-07-16 21:40:49 -07:00
{
2013-05-23 01:01:19 -04:00
return null ;
}
2015-03-25 01:27:15 -04:00
return new FluidStack ( getFluid ( fluidName ), amount );
2013-05-23 01:01:19 -04:00
}
/**
* Returns a read-only map containing Fluid Names and their associated Fluids.
2014-01-29 18:34:23 -08:00
*/
2013-07-16 21:40:49 -07:00
public static Map < String , Fluid > getRegisteredFluids ()
{
2013-05-23 01:01:19 -04:00
return ImmutableMap . copyOf ( fluids );
}
/**
* Returns a read-only map containing Fluid Names and their associated IDs.
2014-01-29 18:34:23 -08:00
*/
2015-04-07 20:06:55 -07:00
@Deprecated //Change return type to <Fluid, Integer> in 1.8.3
2013-07-16 21:40:49 -07:00
public static Map < String , Integer > getRegisteredFluidIDs ()
2015-04-07 20:06:55 -07:00
{
return ImmutableMap . copyOf ( fluidNames . inverse ());
}
2013-05-23 01:01:19 -04:00
/**
2015-03-25 01:27:15 -04:00
* Returns a read-only map containing Fluid IDs and their associated Fluids.
2015-04-07 20:06:55 -07:00
* In 1.8.3, this will change to just 'getRegisteredFluidIDs'
2014-01-29 18:34:23 -08:00
*/
2015-04-07 20:06:55 -07:00
public static Map < Fluid , Integer > getRegisteredFluidIDsByFluid ()
2013-07-16 21:40:49 -07:00
{
2013-05-23 01:01:19 -04:00
return ImmutableMap . copyOf ( fluidIDs );
}
2013-09-05 12:08:16 -04:00
public static Fluid lookupFluidForBlock ( Block block )
{
if ( fluidBlocks == null )
{
2014-04-02 23:53:05 -07:00
BiMap < Block , Fluid > tmp = HashBiMap . create ();
2013-09-05 12:08:16 -04:00
for ( Fluid fluid : fluids . values ())
{
2014-01-29 18:34:23 -08:00
if ( fluid . canBePlacedInWorld () && fluid . getBlock () != null )
2013-09-05 12:08:16 -04:00
{
2014-04-02 23:53:05 -07:00
tmp . put ( fluid . getBlock (), fluid );
2013-09-05 12:08:16 -04:00
}
}
2014-04-02 23:53:05 -07:00
fluidBlocks = tmp ;
2013-09-05 12:08:16 -04:00
}
return fluidBlocks . get ( block );
}
2015-04-05 16:13:17 -04:00
2013-07-16 21:40:49 -07:00
public static class FluidRegisterEvent extends Event
{
2013-05-23 01:01:19 -04:00
public final String fluidName ;
public final int fluidID ;
2013-07-16 21:40:49 -07:00
public FluidRegisterEvent ( String fluidName , int fluidID )
{
2013-05-23 01:01:19 -04:00
this . fluidName = fluidName ;
this . fluidID = fluidID ;
}
}
2014-01-29 18:34:23 -08:00
public static int getMaxID ()
{
return maxID ;
}
2015-04-11 17:18:53 -04:00
public static String getDefaultFluidName ( Fluid key )
{
2015-04-18 21:37:45 -04:00
String name = masterFluidReference . inverse (). get ( key );
if ( Strings . isNullOrEmpty ( name )) {
FMLLog . getLogger (). log ( Level . ERROR , "The fluid registry is corrupted. A fluid {} {} is not properly registered. The mod that registered this is broken" , key . getClass (). getName (), key . getName ());
throw new IllegalStateException ( "The fluid registry is corrupted" );
}
return name ;
2015-04-11 17:18:53 -04:00
}
public static void loadFluidDefaults ( NBTTagCompound tag )
{
Set < String > defaults = Sets . newHashSet ();
if ( tag . hasKey ( "DefaultFluidList" , 9 ))
{
FMLLog . getLogger (). log ( Level . DEBUG , "Loading persistent fluid defaults from world" );
NBTTagList tl = tag . getTagList ( "DefaultFluidList" , 8 );
for ( int i = 0 ; i < tl . tagCount (); i ++ )
{
defaults . add ( tl . getStringTagAt ( i ));
}
}
else
{
FMLLog . getLogger (). log ( Level . DEBUG , "World is missing persistent fluid defaults - using local defaults" );
}
2015-06-03 19:26:53 -04:00
loadFluidDefaults ( HashBiMap . create ( fluidIDs ), defaults );
2015-04-11 17:18:53 -04:00
}
public static void writeDefaultFluidList ( NBTTagCompound forgeData )
{
NBTTagList tagList = new NBTTagList ();
for ( Entry < String , Fluid > def : fluids . entrySet ())
{
tagList . appendTag ( new NBTTagString ( getDefaultFluidName ( def . getValue ())));
}
forgeData . setTag ( "DefaultFluidList" , tagList );
}
2015-04-18 21:37:45 -04:00
public static void validateFluidRegistry ()
{
Set < Fluid > illegalFluids = Sets . newHashSet ();
for ( Fluid f : fluids . values ())
{
if ( ! masterFluidReference . containsValue ( f ))
{
illegalFluids . add ( f );
}
}
if ( ! illegalFluids . isEmpty ())
{
FMLLog . getLogger (). log ( Level . FATAL , "The fluid registry is corrupted. Something has inserted a fluid without registering it" );
FMLLog . getLogger (). log ( Level . FATAL , "There is {} unregistered fluids" , illegalFluids . size ());
for ( Fluid f : illegalFluids )
{
FMLLog . getLogger (). log ( Level . FATAL , " Fluid name : {}, type: {}" , f . getName (), f . getClass (). getName ());
}
FMLLog . getLogger (). log ( Level . FATAL , "The mods that own these fluids need to register them properly" );
throw new IllegalStateException ( "The fluid map contains fluids unknown to the master fluid registry" );
}
}
2015-04-20 09:06:23 -04:00
static RegistryDelegate < Fluid > makeDelegate ( Fluid fl )
{
return delegates . get ( fl );
}
private static class FluidDelegate implements RegistryDelegate < Fluid >
{
private String name ;
private Fluid fluid ;
FluidDelegate ( Fluid fluid , String name )
{
this . fluid = fluid ;
this . name = name ;
}
@Override
public Fluid get ()
{
return fluid ;
}
@Override
public String name ()
{
return name ;
}
@Override
public Class < Fluid > type ()
{
return Fluid . class ;
}
void rebind ()
{
fluid = fluids . get ( name );
}
}
2015-06-18 14:14:46 +03:00
public static void onTextureStitchedPre ( TextureMap map )
{
for ( Fluid fluid : fluids . values ())
{
if ( fluid . getStill () != null )
{
TextureAtlasSprite still = map . registerSprite ( fluid . getStill ());
fluid . setStillIcon ( still );
}
if ( fluid . getFlowing () != null )
{
TextureAtlasSprite flowing = map . registerSprite ( fluid . getFlowing ());
fluid . setStillIcon ( flowing );
}
}
}
2015-04-20 09:06:23 -04:00
}