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
* /
2013-05-23 05:01:19 +00:00
package net.minecraftforge.fluids ;
2018-08-02 05:28:22 +00:00
import java.util.Collections ;
2013-05-23 05:01:19 +00:00
import java.util.Map ;
2015-04-08 03:06:55 +00:00
import java.util.Map.Entry ;
2015-04-11 21:18:53 +00:00
import java.util.Set ;
2018-06-06 15:37:56 +00:00
import net.minecraftforge.fml.ModThreadContext ;
2013-05-23 05:01:19 +00:00
import net.minecraft.block.Block ;
2014-01-30 02:34:23 +00:00
import net.minecraft.init.Blocks ;
2015-04-11 21:18:53 +00:00
import net.minecraft.nbt.NBTTagCompound ;
import net.minecraft.nbt.NBTTagList ;
import net.minecraft.nbt.NBTTagString ;
2015-06-18 11:14:46 +00:00
import net.minecraft.util.ResourceLocation ;
2016-03-07 00:54:47 +00:00
import net.minecraft.util.text.translation.I18n ;
2013-05-23 05:01:19 +00:00
import net.minecraftforge.common.MinecraftForge ;
2015-04-19 01:37:45 +00:00
import com.google.common.base.Strings ;
2013-05-23 05:01:19 +00:00
import com.google.common.collect.BiMap ;
import com.google.common.collect.HashBiMap ;
import com.google.common.collect.ImmutableMap ;
2016-01-02 13:38:18 +00:00
import com.google.common.collect.ImmutableSet ;
2014-01-30 02:34:23 +00:00
import com.google.common.collect.Maps ;
2015-04-11 21:18:53 +00:00
import com.google.common.collect.Sets ;
2013-05-23 05:01:19 +00:00
2018-06-15 19:03:35 +00:00
import net.minecraftforge.fml.ModContainer ;
2018-06-11 01:12:46 +00:00
import net.minecraftforge.eventbus.api.Event ;
2017-06-19 22:02:18 +00:00
import net.minecraftforge.registries.IRegistryDelegate ;
2018-06-21 19:37:32 +00:00
import org.apache.logging.log4j.LogManager ;
import org.apache.logging.log4j.Logger ;
import org.apache.logging.log4j.Marker ;
import org.apache.logging.log4j.MarkerManager ;
2013-12-17 01:18:48 +00:00
2017-01-11 23:17:56 +00:00
import javax.annotation.Nullable ;
2013-05-23 05:01:19 +00:00
/ * *
* Handles Fluid registrations . Fluids MUST be registered in order to function .
* /
2013-07-17 04:40:49 +00:00
public abstract class FluidRegistry
{
2018-08-27 17:10:07 +00:00
private static final Logger LOGGER = LogManager . getLogger ( ) ;
2018-06-21 19:37:32 +00:00
private static final Marker FLUIDS = MarkerManager . getMarker ( " FLUIDS " ) ;
2013-05-23 05:01:19 +00:00
static int maxID = 0 ;
2015-03-25 05:27:15 +00:00
static BiMap < String , Fluid > fluids = HashBiMap . create ( ) ;
static BiMap < Fluid , Integer > fluidIDs = HashBiMap . create ( ) ;
2015-04-08 03:06:55 +00:00
static BiMap < Integer , String > fluidNames = HashBiMap . create ( ) ; //Caching this just makes some other calls faster
2013-09-05 16:08:16 +00:00
static BiMap < Block , Fluid > fluidBlocks ;
2015-04-05 20:13:17 +00:00
2015-04-11 21:18:53 +00: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 13:26:27 +00:00
static Map < Fluid , FluidDelegate > delegates = Maps . newHashMap ( ) ;
2015-04-11 21:18:53 +00:00
2016-01-02 13:38:18 +00:00
static boolean universalBucketEnabled = false ;
static Set < Fluid > bucketFluids = Sets . newHashSet ( ) ;
2018-07-18 03:37:20 +00:00
public static final Fluid WATER = new Fluid ( " water " , new ResourceLocation ( " blocks/water_still " ) , new ResourceLocation ( " blocks/water_flow " ) , new ResourceLocation ( " blocks/water_overlay " ) ) {
2013-11-12 09:05:13 +00:00
@Override
2015-11-24 15:05:35 +00:00
public String getLocalizedName ( FluidStack fs ) {
2016-03-07 00:54:47 +00:00
return I18n . translateToLocal ( " tile.water.name " ) ;
2013-11-12 09:05:13 +00:00
}
2016-05-18 12:11:56 +00:00
} . setBlock ( Blocks . WATER ) . setUnlocalizedName ( Blocks . WATER . getUnlocalizedName ( ) ) ;
2015-04-05 20:13:17 +00:00
2015-06-18 11:14:46 +00:00
public static final Fluid LAVA = new Fluid ( " lava " , new ResourceLocation ( " blocks/lava_still " ) , new ResourceLocation ( " blocks/lava_flow " ) ) {
2013-11-12 09:05:13 +00:00
@Override
2015-11-24 15:05:35 +00:00
public String getLocalizedName ( FluidStack fs ) {
2016-03-07 00:54:47 +00:00
return I18n . translateToLocal ( " tile.lava.name " ) ;
2013-11-12 09:05:13 +00:00
}
2016-05-18 12:11:56 +00:00
} . setBlock ( Blocks . LAVA ) . setLuminosity ( 15 ) . setDensity ( 3000 ) . setViscosity ( 6000 ) . setTemperature ( 1300 ) . setUnlocalizedName ( Blocks . LAVA . getUnlocalizedName ( ) ) ;
2013-05-23 05:01:19 +00:00
2013-07-17 04:40:49 +00:00
static
{
2013-05-23 05:01:19 +00:00
registerFluid ( WATER ) ;
registerFluid ( LAVA ) ;
}
2013-07-17 04:40:49 +00:00
private FluidRegistry ( ) { }
2013-05-23 05:01:19 +00:00
/ * *
* Called by Forge to prepare the ID map for server - > client sync .
2014-01-30 02:34:23 +00:00
* Modders , DO NOT call this .
* /
2015-04-11 21:18:53 +00:00
public static void initFluidIDs ( BiMap < Fluid , Integer > newfluidIDs , Set < String > defaultNames )
2013-07-17 04:40:49 +00:00
{
2013-05-23 05:01:19 +00:00
maxID = newfluidIDs . size ( ) ;
2015-06-03 23:26:53 +00:00
loadFluidDefaults ( newfluidIDs , defaultNames ) ;
2013-05-23 05:01:19 +00:00
}
/ * *
2015-04-11 21:18:53 +00: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-11-24 15:05:35 +00:00
* @param localFluidIDs
* @param defaultNames
2015-04-11 21:18:53 +00:00
* /
2015-06-03 23:26:53 +00:00
private static void loadFluidDefaults ( BiMap < Fluid , Integer > localFluidIDs , Set < String > defaultNames )
2015-04-11 21:18:53 +00: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 23:26:53 +00:00
BiMap < String , Fluid > localFluids = HashBiMap . create ( fluids ) ;
2015-04-11 21:18:53 +00: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 ) {
2018-06-21 19:37:32 +00:00
LOGGER . error ( FLUIDS , " The fluid {} (specified as {}) is missing from this instance - it will be removed " , derivedName , defaultName ) ;
2015-04-11 21:18:53 +00:00
continue ;
}
fluid = masterFluidReference . get ( localDefault ) ;
2018-06-21 19:37:32 +00:00
LOGGER . error ( FLUIDS , " The fluid {} specified as default is not present - it will be reverted to default {} " , defaultName , localDefault ) ;
2015-04-11 21:18:53 +00:00
}
2018-06-21 19:37:32 +00:00
LOGGER . debug ( FLUIDS , " The fluid {} has been selected as the default fluid for {} " , defaultName , fluid . getName ( ) ) ;
2015-06-03 23:26:53 +00:00
Fluid oldFluid = localFluids . put ( fluid . getName ( ) , fluid ) ;
Integer id = localFluidIDs . remove ( oldFluid ) ;
localFluidIDs . put ( fluid , id ) ;
}
2015-07-09 20:40:51 +00:00
BiMap < Integer , String > localFluidNames = HashBiMap . create ( ) ;
2015-06-03 23:26:53 +00:00
for ( Entry < Fluid , Integer > e : localFluidIDs . entrySet ( ) ) {
localFluidNames . put ( e . getValue ( ) , e . getKey ( ) . getName ( ) ) ;
2015-04-11 21:18:53 +00:00
}
2015-06-03 23:26:53 +00:00
fluidIDs = localFluidIDs ;
fluids = localFluids ;
fluidNames = localFluidNames ;
2015-04-11 21:18:53 +00:00
fluidBlocks = null ;
2015-04-20 13:06:23 +00:00
for ( FluidDelegate fd : delegates . values ( ) )
{
fd . rebind ( ) ;
}
2013-05-23 05:01:19 +00:00
}
/ * *
2015-04-11 21:18:53 +00: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 21:36:27 +00:00
*
2013-05-23 05:01:19 +00:00
* @param fluid
* The fluid to register .
2015-04-11 21:18:53 +00:00
* @return True if the fluid was registered as the current default fluid , false if it was only registered as an alternative
2014-01-30 02:34:23 +00:00
* /
2013-07-17 04:40:49 +00:00
public static boolean registerFluid ( Fluid fluid )
{
2015-04-11 21:18:53 +00:00
masterFluidReference . put ( uniqueName ( fluid ) , fluid ) ;
2015-04-20 13:06:23 +00:00
delegates . put ( fluid , new FluidDelegate ( fluid , fluid . getName ( ) ) ) ;
2015-04-08 11:26:40 +00:00
if ( fluids . containsKey ( fluid . getName ( ) ) )
2013-07-17 04:40:49 +00:00
{
2013-05-23 05:01:19 +00:00
return false ;
}
fluids . put ( fluid . getName ( ) , fluid ) ;
2015-04-10 20:38:45 +00:00
maxID + + ;
fluidIDs . put ( fluid , maxID ) ;
2015-04-08 03:06:55 +00:00
fluidNames . put ( maxID , fluid . getName ( ) ) ;
2015-04-11 21:18:53 +00:00
defaultFluidName . put ( fluid . getName ( ) , uniqueName ( fluid ) ) ;
2013-05-23 05:01:19 +00:00
MinecraftForge . EVENT_BUS . post ( new FluidRegisterEvent ( fluid . getName ( ) , maxID ) ) ;
return true ;
}
2015-04-11 21:18:53 +00:00
private static String uniqueName ( Fluid fluid )
{
2018-06-21 19:37:32 +00:00
return ModThreadContext . get ( ) . getActiveContainer ( ) . getPrefix ( ) + " : " + fluid . getName ( ) ;
2015-04-11 21:18:53 +00:00
}
/ * *
* 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-17 04:40:49 +00:00
public static boolean isFluidRegistered ( Fluid fluid )
{
2015-04-11 21:27:14 +00:00
return fluid ! = null & & fluids . containsKey ( fluid . getName ( ) ) ;
2013-05-23 05:01:19 +00:00
}
2013-07-17 04:40:49 +00:00
public static boolean isFluidRegistered ( String fluidName )
{
2015-03-25 05:27:15 +00:00
return fluids . containsKey ( fluidName ) ;
2013-05-23 05:01:19 +00:00
}
2013-07-17 04:40:49 +00:00
public static Fluid getFluid ( String fluidName )
{
2013-05-23 05:01:19 +00:00
return fluids . get ( fluidName ) ;
}
2015-03-25 05:27:15 +00:00
public static String getFluidName ( Fluid fluid )
2013-07-17 04:40:49 +00:00
{
2015-03-25 05:27:15 +00:00
return fluids . inverse ( ) . get ( fluid ) ;
2013-05-23 05:01:19 +00:00
}
2015-03-25 05:27:15 +00:00
public static String getFluidName ( FluidStack stack )
2013-07-17 04:40:49 +00:00
{
2015-04-20 13:06:23 +00:00
return getFluidName ( stack . getFluid ( ) ) ;
2013-05-23 05:01:19 +00:00
}
2017-01-11 23:17:56 +00:00
@Nullable
2013-07-17 04:40:49 +00:00
public static FluidStack getFluidStack ( String fluidName , int amount )
{
2015-03-25 05:27:15 +00:00
if ( ! fluids . containsKey ( fluidName ) )
2013-07-17 04:40:49 +00:00
{
2013-05-23 05:01:19 +00:00
return null ;
}
2015-03-25 05:27:15 +00:00
return new FluidStack ( getFluid ( fluidName ) , amount ) ;
2013-05-23 05:01:19 +00:00
}
/ * *
* Returns a read - only map containing Fluid Names and their associated Fluids .
2014-01-30 02:34:23 +00:00
* /
2013-07-17 04:40:49 +00:00
public static Map < String , Fluid > getRegisteredFluids ( )
{
2013-05-23 05:01:19 +00:00
return ImmutableMap . copyOf ( fluids ) ;
}
/ * *
* Returns a read - only map containing Fluid Names and their associated IDs .
2015-12-10 10:54:00 +00:00
* Modders should never actually use this , use the String names .
2014-01-30 02:34:23 +00:00
* /
2015-12-10 10:54:00 +00:00
@Deprecated
2015-11-24 15:05:35 +00:00
public static Map < Fluid , Integer > getRegisteredFluidIDs ( )
2015-04-08 03:06:55 +00:00
{
2015-11-24 15:05:35 +00:00
return ImmutableMap . copyOf ( fluidIDs ) ;
2015-04-08 03:06:55 +00:00
}
2016-01-02 13:38:18 +00:00
/ * *
* Enables the universal bucket in forge .
* Has to be called before pre - initialization .
* Actually just call it statically in your mod class .
* /
public static void enableUniversalBucket ( )
{
2018-06-21 19:37:32 +00:00
universalBucketEnabled = true ;
2016-01-02 13:38:18 +00:00
}
public static boolean isUniversalBucketEnabled ( )
{
return universalBucketEnabled ;
}
/ * *
* Registers a fluid with the universal bucket .
* This only has an effect if the universal bucket is enabled .
* @param fluid The fluid that the bucket shall be able to hold
* @return True if the fluid was added successfully , false if it already was registered or couldn ' t be registered with the bucket .
* /
public static boolean addBucketForFluid ( Fluid fluid )
{
if ( fluid = = null ) {
return false ;
}
// register unregistered fluids
if ( ! isFluidRegistered ( fluid ) )
{
registerFluid ( fluid ) ;
}
return bucketFluids . add ( fluid ) ;
}
/ * *
* All fluids registered with the universal bucket
* @return An immutable set containing the fluids
* /
public static Set < Fluid > getBucketFluids ( )
{
2018-08-02 05:28:22 +00:00
return Collections . unmodifiableSet ( bucketFluids ) ;
2016-01-02 13:38:18 +00:00
}
2013-09-05 16:08:16 +00:00
public static Fluid lookupFluidForBlock ( Block block )
{
if ( fluidBlocks = = null )
{
2014-04-03 06:53:05 +00:00
BiMap < Block , Fluid > tmp = HashBiMap . create ( ) ;
2013-09-05 16:08:16 +00:00
for ( Fluid fluid : fluids . values ( ) )
{
2014-01-30 02:34:23 +00:00
if ( fluid . canBePlacedInWorld ( ) & & fluid . getBlock ( ) ! = null )
2013-09-05 16:08:16 +00:00
{
2014-04-03 06:53:05 +00:00
tmp . put ( fluid . getBlock ( ) , fluid ) ;
2013-09-05 16:08:16 +00:00
}
}
2014-04-03 06:53:05 +00:00
fluidBlocks = tmp ;
2013-09-05 16:08:16 +00:00
}
2018-03-17 05:54:23 +00:00
if ( block = = Blocks . FLOWING_WATER )
{
block = Blocks . WATER ;
}
else if ( block = = Blocks . FLOWING_LAVA )
{
block = Blocks . LAVA ;
}
2013-09-05 16:08:16 +00:00
return fluidBlocks . get ( block ) ;
}
2015-04-05 20:13:17 +00:00
2013-07-17 04:40:49 +00:00
public static class FluidRegisterEvent extends Event
{
2016-03-24 08:44:52 +00:00
private final String fluidName ;
private final int fluidID ;
2013-05-23 05:01:19 +00:00
2013-07-17 04:40:49 +00:00
public FluidRegisterEvent ( String fluidName , int fluidID )
{
2013-05-23 05:01:19 +00:00
this . fluidName = fluidName ;
this . fluidID = fluidID ;
}
2016-03-24 08:44:52 +00:00
public String getFluidName ( )
{
return fluidName ;
}
public int getFluidID ( )
{
return fluidID ;
}
2013-05-23 05:01:19 +00:00
}
2014-01-30 02:34:23 +00:00
public static int getMaxID ( )
{
return maxID ;
}
2015-04-11 21:18:53 +00:00
public static String getDefaultFluidName ( Fluid key )
{
2015-04-19 01:37:45 +00:00
String name = masterFluidReference . inverse ( ) . get ( key ) ;
if ( Strings . isNullOrEmpty ( name ) ) {
2018-06-21 19:37:32 +00:00
LOGGER . error ( FLUIDS , " The fluid registry is corrupted. A fluid {} {} is not properly registered. The mod that registered this is broken " , key . getClass ( ) . getName ( ) , key . getName ( ) ) ;
2015-04-19 01:37:45 +00:00
throw new IllegalStateException ( " The fluid registry is corrupted " ) ;
}
return name ;
2015-04-11 21:18:53 +00:00
}
2017-10-03 05:08:16 +00:00
@Nullable
public static String getModId ( @Nullable FluidStack fluidStack )
{
if ( fluidStack ! = null )
{
String defaultFluidName = getDefaultFluidName ( fluidStack . getFluid ( ) ) ;
if ( defaultFluidName ! = null )
{
ResourceLocation fluidResourceName = new ResourceLocation ( defaultFluidName ) ;
return fluidResourceName . getResourceDomain ( ) ;
}
}
return null ;
}
2015-04-11 21:18:53 +00:00
public static void loadFluidDefaults ( NBTTagCompound tag )
{
Set < String > defaults = Sets . newHashSet ( ) ;
if ( tag . hasKey ( " DefaultFluidList " , 9 ) )
{
2018-06-21 19:37:32 +00:00
LOGGER . debug ( FLUIDS , " Loading persistent fluid defaults from world " ) ;
2015-04-11 21:18:53 +00:00
NBTTagList tl = tag . getTagList ( " DefaultFluidList " , 8 ) ;
for ( int i = 0 ; i < tl . tagCount ( ) ; i + + )
{
defaults . add ( tl . getStringTagAt ( i ) ) ;
}
}
else
{
2018-06-21 19:37:32 +00:00
LOGGER . debug ( FLUIDS , " World is missing persistent fluid defaults - using local defaults " ) ;
2015-04-11 21:18:53 +00:00
}
2015-06-03 23:26:53 +00:00
loadFluidDefaults ( HashBiMap . create ( fluidIDs ) , defaults ) ;
2015-04-11 21:18:53 +00: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-19 01:37:45 +00: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 ( ) )
{
2018-06-21 19:37:32 +00:00
LOGGER . fatal ( FLUIDS , " The fluid registry is corrupted. Something has inserted a fluid without registering it " ) ;
LOGGER . fatal ( FLUIDS , " There is {} unregistered fluids " , illegalFluids . size ( ) ) ;
2015-04-19 01:37:45 +00:00
for ( Fluid f : illegalFluids )
{
2018-06-21 19:37:32 +00:00
LOGGER . fatal ( FLUIDS , " Fluid name : {}, type: {} " , f . getName ( ) , f . getClass ( ) . getName ( ) ) ;
2015-04-19 01:37:45 +00:00
}
2018-06-21 19:37:32 +00:00
LOGGER . fatal ( FLUIDS , " The mods that own these fluids need to register them properly " ) ;
2015-04-19 01:37:45 +00:00
throw new IllegalStateException ( " The fluid map contains fluids unknown to the master fluid registry " ) ;
}
}
2015-04-20 13:06:23 +00:00
2017-06-19 22:02:18 +00:00
static IRegistryDelegate < Fluid > makeDelegate ( Fluid fl )
2015-04-20 13:06:23 +00:00
{
return delegates . get ( fl ) ;
}
2017-06-19 22:02:18 +00:00
private static class FluidDelegate implements IRegistryDelegate < Fluid >
2015-04-20 13:06:23 +00:00
{
private String name ;
private Fluid fluid ;
FluidDelegate ( Fluid fluid , String name )
{
this . fluid = fluid ;
this . name = name ;
}
@Override
public Fluid get ( )
{
return fluid ;
}
@Override
2016-04-01 21:13:06 +00:00
public ResourceLocation name ( ) {
2015-11-28 08:01:31 +00:00
return new ResourceLocation ( name ) ;
}
2015-04-20 13:06:23 +00:00
@Override
public Class < Fluid > type ( )
{
return Fluid . class ;
}
void rebind ( )
{
fluid = fluids . get ( name ) ;
}
}
2016-03-07 00:54:47 +00:00
}