2013-05-23 05:01:19 +00:00
package net.minecraftforge.fluids ;
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 ;
2016-01-02 13:38:18 +00:00
import net.minecraftforge.fml.common.LoaderState ;
2015-04-11 21:18:53 +00:00
import org.apache.logging.log4j.Level ;
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
2015-06-01 20:29:34 +00:00
import net.minecraftforge.fml.common.FMLLog ;
import net.minecraftforge.fml.common.Loader ;
import net.minecraftforge.fml.common.ModContainer ;
Initial update to 1.8, Super beta. Most rendering related hooks are out due to major changes in 1.8.
Some notes:
Almost all int x, int y, int z parameters have been changed to BlockPos class
ForgeDirection has been removed, replaced by net.minecraft.util.EnumFacing.
All FML classes have moved from packet cpw.mods.fml to net.minecraftforge.fml
Fluid Rendering has been disabled for the time being, to be re-evaulated and a test mod created for it.
Minecraft now uses a Model based system for rendering blocks and Items. The intention is to expand the model format to better suit modder's needed once it is evaulated.
As such, The model loaders from Forge have been removed, to be replaced by expanding vanilla's model format.
Metadata has been extracted out in Minecraft to IBlockState, which holds a list of properties instead of magic number metadata. DO NOT listen to the fearmongering, you can do EVERYTHING with block states you could previously with metadata.
Stencil Bits are disabled entirely by for the main Display, Modders must enable and recreate the FrameBuffer if they wish to use Stencil Bits.
2014-11-26 03:56:35 +00:00
import net.minecraftforge.fml.common.eventhandler.Event ;
2015-06-01 20:29:34 +00:00
import net.minecraftforge.fml.common.registry.RegistryDelegate ;
2013-12-17 01:18:48 +00:00
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
{
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 ( ) ;
2015-06-18 11:14:46 +00:00
public static final Fluid WATER = new Fluid ( " water " , new ResourceLocation ( " blocks/water_still " ) , new ResourceLocation ( " blocks/water_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.water.name " ) ;
2013-11-12 09:05:13 +00:00
}
2014-02-05 08:05:37 +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
}
2014-02-05 08:05:37 +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 ) {
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 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 )
{
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-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-12-10 10:54:00 +00:00
@Deprecated // Modders should never actually use int ID, use String
2013-07-17 04:40:49 +00:00
public static Fluid getFluid ( int fluidID )
{
2015-06-03 23:26:53 +00:00
return fluidIDs . inverse ( ) . get ( fluidID ) ;
2013-05-23 05:01:19 +00:00
}
2015-12-10 10:54:00 +00:00
@Deprecated // Modders should never actually use int ID, use String
2015-03-25 05:27:15 +00:00
public static int getFluidID ( Fluid fluid )
2013-07-17 04:40:49 +00:00
{
2015-12-10 10:54:00 +00:00
Integer ret = fluidIDs . get ( fluid ) ;
if ( ret = = null ) throw new RuntimeException ( " Attempted to access ID for unregistered fluid, Stop using this method modder! " ) ;
return ret ;
2013-05-23 05:01:19 +00:00
}
2015-12-10 10:54:00 +00:00
@Deprecated // Modders should never actually use int ID, use String
2015-03-25 05:27:15 +00:00
public static int getFluidID ( String fluidName )
2013-07-17 04:40:49 +00:00
{
2015-12-10 10:54:00 +00:00
Integer ret = fluidIDs . get ( getFluid ( fluidName ) ) ;
if ( ret = = null ) throw new RuntimeException ( " Attempted to access ID for unregistered fluid, Stop using this method modder! " ) ;
return ret ;
2013-05-23 05:01:19 +00:00
}
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
}
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 ( )
{
if ( Loader . instance ( ) . hasReachedState ( LoaderState . PREINITIALIZATION ) )
{
FMLLog . getLogger ( ) . log ( Level . ERROR , " Trying to activate the universal filled bucket too late. Call it statically in your Mods class. Mod: {} " , Loader . instance ( ) . activeModContainer ( ) . getName ( ) ) ;
}
else
{
universalBucketEnabled = true ;
}
}
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 ( )
{
return ImmutableSet . copyOf ( bucketFluids ) ;
}
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
}
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
{
2013-05-23 05:01:19 +00:00
public final String fluidName ;
public final int fluidID ;
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 ;
}
}
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 ) ) {
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 21:18:53 +00: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 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 ( ) )
{
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 13:06:23 +00: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 ;
}
2015-11-28 08:01:31 +00:00
@Override
public ResourceLocation getResourceName ( ) {
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
}