Skip to main content

Fluids and Gases

A custom resource has three separate layers:

  1. Registry data teaches storage which items insert or extract the resource.
  2. UI frames let FluidStorage.display() or GasStorage.display() draw a fill level.
  3. Tank entities let the resource render inside physical UtilityCraft tanks.

All three are required for a resource that can appear everywhere. Registration alone does not create any item, texture, or entity.

Register two liquids

The template uses 4,000 mB capsules:

BP/scripts/config/resources.js
import * as DoriosLib from "DoriosLib/index.js";

const FLUID_CAPSULE_AMOUNT = 4000;

DoriosLib.registry.registerFluidItem({
"utilitycraft:example_coolant_capsule": {
type: "example_coolant",
amount: FLUID_CAPSULE_AMOUNT,
output: "utilitycraft:example_empty_fluid_capsule",
},
"utilitycraft:example_biofuel_capsule": {
type: "example_biofuel",
amount: FLUID_CAPSULE_AMOUNT,
output: "utilitycraft:example_empty_fluid_capsule",
},
});

DoriosLib.registry.registerFluidHolder({
"utilitycraft:example_empty_fluid_capsule": {
required: FLUID_CAPSULE_AMOUNT,
types: {
example_coolant: "utilitycraft:example_coolant_capsule",
example_biofuel: "utilitycraft:example_biofuel_capsule",
},
},
});

registerFluidItem() describes a filled item inserted into storage:

FieldMeaning
Item keyExact filled-container item ID.
typeStored liquid type without a namespace prefix.
amountMillibuckets inserted.
outputOptional item returned after insertion, normally the empty holder.

registerFluidHolder() describes an empty item that extracts from storage:

FieldMeaning
Holder keyExact empty-container item ID.
requiredMillibuckets removed to fill one holder. Required for a new holder.
typesMap from every supported liquid type to its filled output item.

Registering an existing filled item replaces its mapping. Registering an existing holder merges its types; a supplied required value updates the holder size.

Register two gases

Gas registration has the same shape but uses an independent storage registry:

BP/scripts/config/resources.js
const GAS_CAPSULE_AMOUNT = 4000;

DoriosLib.registry.registerGasItem({
"utilitycraft:example_hydrogen_capsule": {
type: "example_hydrogen",
amount: GAS_CAPSULE_AMOUNT,
output: "utilitycraft:example_empty_gas_capsule",
},
"utilitycraft:example_exhaust_capsule": {
type: "example_exhaust",
amount: GAS_CAPSULE_AMOUNT,
output: "utilitycraft:example_empty_gas_capsule",
},
});

DoriosLib.registry.registerGasHolder({
"utilitycraft:example_empty_gas_capsule": {
required: GAS_CAPSULE_AMOUNT,
types: {
example_hydrogen: "utilitycraft:example_hydrogen_capsule",
example_exhaust: "utilitycraft:example_exhaust_capsule",
},
},
});

Do not put a gas into the fluid registry or reuse one empty holder across both systems. FluidStorage and GasStorage intentionally keep separate mappings.

Create the holder items

Every identifier in the registry must exist as a normal Behavior Pack item. A filled capsule can be as small as:

BP/items/examples/example_coolant_capsule.json
{
"format_version": "1.21.110",
"minecraft:item": {
"description": {
"identifier": "utilitycraft:example_coolant_capsule",
"menu_category": { "category": "items" }
},
"components": {
"minecraft:icon": "utilitycraft_example_coolant_capsule",
"minecraft:max_stack_size": 16
}
}
}

Create the corresponding empty fluid capsule, biofuel capsule, empty gas capsule, hydrogen capsule, and exhaust capsule, then add their icon keys to RP/textures/item_texture.json and names to the lang file.

Create all 49 display frames

Storage displays calculate a frame from 00 through 48, inclusive. For example_coolant, the Behavior Pack must therefore contain items named:

utilitycraft:example_coolant_00
utilitycraft:example_coolant_01
...
utilitycraft:example_coolant_48

Each frame item uses this pattern:

BP/items/ui/resource_bars/example_coolant/utilitycraft_example_coolant_00.json
{
"format_version": "1.20.80",
"minecraft:item": {
"description": {
"identifier": "utilitycraft:example_coolant_00",
"menu_category": { "category": "none" }
},
"components": {
"minecraft:icon": "utilitycraft:example_coolant_00",
"minecraft:tags": {
"tags": ["utilitycraft:ui_element"]
}
}
}
}

Map every icon key to its matching texture in RP/textures/item_texture.json:

{
"utilitycraft:example_coolant_00": {
"textures": "textures/ui/example_coolant_bar/example_coolant_00"
}
}

Repeat the full sequence for example_biofuel, example_hydrogen, and example_exhaust. A missing frame produces an Invalid item identifier 'utilitycraft:<type>_NN' scripting error when a UI tries to display that fill level.

Create the physical tank entity

UtilityCraft resolves a physical entity by convention:

ResourceRequired Behavior Pack entity IDRequired family
Liquid example_coolantutilitycraft:fluid_tank_example_coolantdorios:fluid_container
Gas example_hydrogenutilitycraft:gas_tank_example_hydrogendorios:gas_container

Copy the matching entity from the Addon Template and change the resource-specific identifier. Preserve its tier health groups, environment sensors, tank family, despawn event, and other controller-facing data.

The Resource Pack client entity may reuse UtilityCraft's registered geometry, animations, and animation controller. Only the identifier and addon-owned texture need to change:

RP/entity/fluids/fluid_tank_example_coolant.json
{
"format_version": "1.8.0",
"minecraft:client_entity": {
"description": {
"identifier": "utilitycraft:fluid_tank_example_coolant",
"materials": { "default": "entity_alphablend" },
"textures": { "default": "textures/entity/example_coolant_fluid" },
"geometry": { "default": "geometry.utilitycraft_fluid_tank_entity" },
"render_controllers": ["controller.render.default"],
"animations": {
"fill": "animation.utilitycraft_fluid_tank_entity.fill"
},
"animation_controllers": [
{ "fluid_fill": "controller.animation.fluid_fill" }
]
}
}
}

For a gas, use geometry.utilitycraft_gas_tank_entity, animation.utilitycraft_gas_tank_entity.fill, and controller.animation.gas_fill from the matching template client entity.

Resource checklist

For each type, verify:

  • Its filled and empty container items exist.
  • Its item and holder registrations use the same amount.
  • Every frame item and texture from 00 through 48 exists.
  • Its BP tank entity ID follows the exact fluid/gas naming convention.
  • Its RP client entity uses the same identifier and the correct family of shared geometry/controllers.
  • A machine can insert, extract, display, and transfer the resource without content-log errors.

For storage behavior, see Liquid IO, Gas IO, FluidStorage, and GasStorage.

Continue with Plants and bonsais.