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 ;
import org.apache.logging.log4j.Level ;
2013-05-23 05:01:19 +00:00
import net.minecraft.block.Block ;
2015-06-18 11:14:46 +00:00
import net.minecraft.client.renderer.texture.TextureAtlasSprite ;
import net.minecraft.client.renderer.texture.TextureMap ;
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 ;
2013-11-12 09:05:13 +00:00
import net.minecraft.util.StatCollector ;
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 ;
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-27 21:36:27 +00:00
*
2013-05-23 05:01:19 +00:00
* @author King Lemming , CovertJaguar ( LiquidDictionary )
2013-07-27 21:36:27 +00:00
*
2013-05-23 05:01:19 +00:00
* /
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
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
public String getLocalizedName ( ) {
return StatCollector . translateToLocal ( " tile.water.name " ) ;
}
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
public String getLocalizedName ( ) {
return StatCollector . translateToLocal ( " tile.lava.name " ) ;
}
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
public static int renderIdFluid = - 1 ;
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-06-03 23:26:53 +00:00
* @param newfluidIDs
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 ) ;
}
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-03-25 05:27:15 +00:00
public static int getFluidID ( Fluid fluid )
2013-07-17 04:40:49 +00:00
{
2015-06-03 23:26:53 +00:00
return fluidIDs . get ( fluid ) ;
2013-05-23 05:01:19 +00:00
}
2015-03-25 05:27:15 +00:00
public static int getFluidID ( String fluidName )
2013-07-17 04:40:49 +00:00
{
2015-06-03 23:26:53 +00:00
return fluidIDs . get ( getFluid ( fluidName ) ) ;
2013-05-23 05:01:19 +00:00
}
2015-04-08 03:06:55 +00:00
@Deprecated //Remove in 1.8.3
2013-07-17 04:40:49 +00:00
public static String getFluidName ( int fluidID )
{
2015-04-08 03:06:55 +00:00
return fluidNames . get ( fluidID ) ;
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 .
2014-01-30 02:34:23 +00:00
* /
2015-04-08 03:06:55 +00:00
@Deprecated //Change return type to <Fluid, Integer> in 1.8.3
2013-07-17 04:40:49 +00:00
public static Map < String , Integer > getRegisteredFluidIDs ( )
2015-04-08 03:06:55 +00:00
{
return ImmutableMap . copyOf ( fluidNames . inverse ( ) ) ;
}
2013-05-23 05:01:19 +00:00
/ * *
2015-03-25 05:27:15 +00:00
* Returns a read - only map containing Fluid IDs and their associated Fluids .
2015-04-08 03:06:55 +00:00
* In 1 . 8 . 3 , this will change to just ' getRegisteredFluidIDs '
2014-01-30 02:34:23 +00:00
* /
2015-04-08 03:06:55 +00:00
public static Map < Fluid , Integer > getRegisteredFluidIDsByFluid ( )
2013-07-17 04:40:49 +00:00
{
2013-05-23 05:01:19 +00:00
return ImmutableMap . copyOf ( fluidIDs ) ;
}
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 ;
}
@Override
public Class < Fluid > type ( )
{
return Fluid . class ;
}
void rebind ( )
{
fluid = fluids . get ( name ) ;
}
}
2015-06-18 11:14:46 +00: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 13:06:23 +00:00
}