Creating a Custom Fluid
Architectury provides base classes so you can add a working fluid - flowing, source, liquid block, and bucket - from common code. This page is the practical guide; Fluid Base Classes covers each class in more detail.
The pieces
A complete fluid is made of four registered objects, all described by a single
ArchitecturyFluidAttributes:
| Piece | Class | Registry |
|---|---|---|
| Source fluid | ArchitecturyFlowingFluid.Source | Registries.FLUID |
| Flowing fluid | ArchitecturyFlowingFluid.Flowing | Registries.FLUID |
| Liquid block | ArchitecturyLiquidBlock | Registries.BLOCK |
| Bucket item | ArchitecturyBucketItem | Registries.ITEM |
Describing the fluid
Build the attributes with SimpleArchitecturyFluidAttributes. It takes suppliers for the flowing
and source fluids (which you register next), then a chain of settings:
public static final ArchitecturyFluidAttributes OIL_ATTRIBUTES =
SimpleArchitecturyFluidAttributes.of(() -> OIL_FLOWING.get(), () -> OIL_STILL.get())
.sourceTexture(Identifier.fromNamespaceAndPath(MOD_ID, "block/oil_still"))
.flowingTexture(Identifier.fromNamespaceAndPath(MOD_ID, "block/oil_flow"))
.color(0xFF1A1A1A)
.density(2000)
.viscosity(2000)
.blockSupplier(() -> OIL_BLOCK)
.bucketItemSupplier(() -> OIL_BUCKET);
The builder exposes every fluid property, each returning the builder so you can chain them:
- Rendering:
sourceTexture,flowingTexture,overlayTexture,color,luminosity. - Physics:
density,temperature,viscosity,lighterThanAir,slopeFindDistance,dropOff,tickDelay,explosionResistance,convertToSource. - Misc:
rarity,fillSound,emptySound. - Links:
blockSupplier/block, andbucketItemSupplier/bucketItem.
Registering the pieces
Register all four through DeferredRegister. The source
and flowing fluids both take the shared attributes:
public static final RegistrySupplier<ArchitecturyFlowingFluid.Source> OIL_STILL =
FLUIDS.register("oil", () -> new ArchitecturyFlowingFluid.Source(OIL_ATTRIBUTES));
public static final RegistrySupplier<ArchitecturyFlowingFluid.Flowing> OIL_FLOWING =
FLUIDS.register("flowing_oil", () -> new ArchitecturyFlowingFluid.Flowing(OIL_ATTRIBUTES));
public static final RegistrySupplier<LiquidBlock> OIL_BLOCK = BLOCKS.register("oil", () -> {
ResourceKey<Block> key = ResourceKey.create(Registries.BLOCK,
Identifier.fromNamespaceAndPath(MOD_ID, "oil"));
return new ArchitecturyLiquidBlock(OIL_STILL, BlockBehaviour.Properties.of().liquid().setId(key));
});
public static final RegistrySupplier<Item> OIL_BUCKET = ITEMS.register("oil_bucket", () -> {
ResourceKey<Item> key = ResourceKey.create(Registries.ITEM,
Identifier.fromNamespaceAndPath(MOD_ID, "oil_bucket"));
return new ArchitecturyBucketItem(OIL_STILL, new Item.Properties().craftRemainder(Items.BUCKET).setId(key));
});
The attributes reference the fluids, and the fluids reference the attributes. Because the builder
takes suppliers (() -> OIL_FLOWING.get(), blockSupplier(() -> OIL_BLOCK)), the references
resolve lazily - so the order in which these fields initialize doesn't matter.
Remember the setId(...) on the block and bucket Properties, as with any
item or block registration.
Next
Fluid Base Classes documents SimpleArchitecturyFluidAttributes
(every builder setting), ArchitecturyFlowingFluid, ArchitecturyLiquidBlock, and
ArchitecturyBucketItem in full.