Minecraft Modding: Fluids, Tanks and Buckets

Background


In vanilla Minecraft there are two types of "fluid": water and lava. These are considered fluid (also known as liquid) because:

  • There is a source block which will continue to provide the fluid indefinitely, and flow blocks which spread out own their own to fill space in the world.
  • They have models that relate to the "level" of the fluid in the block position.
  • They have texture animations that make them appear to be flowing.
  • They are not solid -- entities can move into them.
  • It is possible to fully submerge in them, in which case they cause a render overlay (i.e. world looks blue when under water).
  • Being in flowing fluid will cause an entity to be pushed along with the flow.
  • You can fill a bucket with them.
Making custom fluids has always been popular for modders so Forge added a custom fluid system. In addition to the "classic" fluid that behaves similarly to vanilla fluids they've added:
  • "Finite" fluids that only have a given amount and once that finishes flowing stops.
  • Gases which are basically fluids that are lighter than air.
  • Different viscosities to allow different rates of flow.
  • A "universal" bucket because the vanilla bucket has some hard-coding specific to the vanilla fluids.
  • A "tank" system which basically allows something (e.g. tile entity) to have an inventory containing a fluid.
The Forge system contains a number of interfaces, base blocks that implement these interfaces, and a number of capabilities. so might seem possibly complicated but for most purposes is fairly straightforward.

A "tank" is a capability that implements IFluidTank (which allows fluid interaction with inventories) and IFluidHandler (which allows something to store a fluid with a level).

It is possible for a block (by way of a tile entity), an item or an entity to have a tank capability. I explain how to attach the capability to these below.

The FluidTank is the default implementation of the tank capability and has two associated helper classes, FluidTankInfo and IFluidTankProperties, which contain information about capacity and draining/filling and which you probably do not need to customize.

Creating A Custom Fluid


The Fluid itself is necessary for all the other things I explain later in the tutorial. You will need this fluid if you want to place the fluid in the world as a fluid block, if you want to store the fluid in a tile entity "tank" or you want to hold the fluid in an item "tank".

Creating A Custom Fluid Block


A fluid block is the fluid itself, and is placed as a source block and then appears to flow outwards.

To create a custom such fluid block, see Jabelar's Custom Fluid Block Tutorial.

Creating A Custom "Tank" Item / ItemStack


Items can be tanks (i.e. having the IFluidHandler capability) but as always as always remember that an Item is a singleton and so need to be manipulated with ItemStack.

Check out Jabelar's Fluid Handling Item Tutorial.

Creating A Custom "Tank" Block / TileEntity

A block can become a tank by having an associate tile entity that is a fluid handler. This would be good for things like machines that accept fluid directly, for things like cauldrons and such.

Check out Jabelar's Fluid Handling TileEntity Tutorial.

Universal Buckets


Since the vanilla bucket item is hard-coded for water, lava and milk, Forge has provided a UniversalBucket class that can be enabled so that your custom fluids can also work with buckets.

Important: The universal bucket must be enabled, by making a static call to the FluidRegistry.enableUniversalBucket() method from your main mod class. This has to be enabled before the pre-init phase, so it is best to simply call it directly in your main mod class. For example put the following in your main mod class:

static {
   FluidRegistry.enableUniversalBucket();
       }

Then after you register each custom fluid make a call to FluidRegistry.addBucketForFluid() for each custom fluid you want a bucket added for. This will use Forge's universal bucket.

Key Point: If you need an ItemStack containing a UniversalBucket filled with your custom fluid for versions 1.12+ use FluidUtil.getFilledBucket(new FluidStack(ModItems.MY_COOL_FLUID, FLUID.BUCKET_VOLUME)) where you can change the amount or use the alternate FluidStack constructor that also takes NBT data.

Creating Custom Buckets


It is possible to extend UniveralBucket and create special buckets with their own models, textures and extended behavior. For example Choonster creates wooden buckets and stone buckets in his TestMod3 example code.

1 comment:

  1. Where is the Jabelar's Fluid Handling TileEntity Tutorial?

    ReplyDelete