Skip to content

API Fluids

Piggo41 edited this page Oct 16, 2026 · 10 revisions

Fluids

Lua API / Fluids

Each custom fluid has a key and separate flowing and still block IDs. The IDs do not need to be adjacent. Fluids with the same material still have separate flow settings, textures, bucket behavior, and declared interactions.

On this page

Quick registration

betamoon.fluids:add(definition) validates the complete declaration before allocating either block or the optional bucket. It returns a read-only fluid reference.

local acid = betamoon.fluids:add {
    key = "my_mod:fluid/acid",
    material = betamoon.mc.blockMaterials.water,
    preset = "water",

    blocks = {
        flowing = { id = 180, key = "my_mod:block/acid_flowing" },
        still = { id = 184, key = "my_mod:block/acid_still" }
    },

    bucket = {
        id = 5200,
        key = "my_mod:item/acid_bucket",
        displayName = "Acid Bucket",
        texture = "items/acid_bucket.png"
    },

    appearance = {
        still = "blocks/acid_still.png",
        flowing = "blocks/acid_flowing.png",
        tint = 0x83D936,
        renderPass = "translucent",
        light = 0,
        lightOpacity = 3
    },

    flow = {
        tickRate = 8,
        finite = true
    },

    displacement = { blocks = "drop" },

    entity = {
        movement = "water", currentScale = 0.6,
        drowning = false, countsAsWet = false, extinguishesFire = false,
        contactDamage = 2, contactIntervalTicks = 10
    },

    camera = { fogColor = 0x29451B, fogDensity = 0.16, overlay = false }
}

The flowing and still blocks do not receive ordinary inventory forms. Use the bucket or another item/block of your own design when players need to carry or place the fluid. The intermediate custom-fluid example is a runnable lesson with an animated fluid, bucket, contact damage, and eye-fluid fog. Copy its example/ texture folder beside the script. Keep its numbered filename when using its example: keys; use your own namespace when adapting it into another mod.

Fluid fields

Field Type Default / behavior
key string Required canonical namespace:fluid/name key; namespace:name is accepted here as typed shorthand.
material water or lava Required block material. See compatibility limits.
preset neutral, water, or lava neutral; copies initial defaults before explicit fields are applied.
appearance table Required still/flowing textures and optional render properties.
flow table Optional simulation overrides.
displacement table Optional ordinary-block displacement policy.
entity table Optional movement, breathing, wetness, fire, and damage policy.
camera table Optional eye-fluid fog and overlay policy.
blocks table Required by fluids:add; one flowing and one still declaration.
bucket table or false Optional filled bucket. Omit it or use false for no bucket.

The preset selects fluid defaults; material does not select the preset automatically.

appearance

Field Type Default / behavior
still texture or atlas integer Required top/bottom texture.
flowing texture or atlas integer Required side and moving-surface texture.
tint RGB integer 0xFFFFFF.
renderPass solid or translucent solid for the lava preset, otherwise translucent.
light integer 0–15 15 for the lava preset, otherwise 0.
lightOpacity integer 0–255 255 for the lava preset, otherwise 3.

Texture values accept the same registered texture references, namespaced asset keys, direct PNG paths, and atlas indices as the block/item APIs. See Textures.

flow

Field Range / values Default
tickRate integer 1–1200 5 for neutral/water; 30 for lava.
levelStep integer 1–7 1 for neutral/water; 2 for lava.
slopeSearch integer 0–8 4.
finite boolean false for water; true for neutral/lava. true prevents new sources; false uses the two-adjacent-source rule.
sourceCreation never, two_adjacent two_adjacent for water; otherwise never.
retreatDelayChance number 0–1 0.75 for lava; otherwise 0.
dimensions table Optional Nether partial override.

The supported dimension keys are nether, hell, and minecraft:dimension/hell; they name the same override, so declare only one. An override accepts tickRate, levelStep, or both. The lava preset uses level step 1 in the Nether.

finite controls source renewal: true is equivalent to sourceCreation = "never"; false is equivalent to sourceCreation = "two_adjacent". If both fields are supplied, they must agree. Two adjacent sources and support below are required to create a new source. This setting does not conserve total fluid volume as fluid spreads.

Metadata is reserved for fluid state: 0 is a source, 1–7 are horizontal levels, and 8–15 are falling states. Custom block metadata/state declarations are therefore not compatible with fluid blocks.

displacement

displacement.blocks accepts:

  • drop: break an eligible replaceable block and emit its normal drops;
  • destroy: replace it without drops;
  • block: do not replace ordinary blocks.

Another registered fluid and any block with a tile entity always block displacement. Cross-fluid replacement must be declared through an interaction.

entity

Entity behavior is selected by registered fluid identity, independently of material. Omitted fields copy the selected preset's defaults.

Field Values Behavior
movement none, water, lava Native-compatible swimming or lava movement; none keeps ordinary movement.
currentScale number 0–8 Multiplies current acceleration; 0 disables currents.
drowning boolean Living entities consume air while their eye is immersed; also controls the player's air HUD.
countsAsWet boolean Body contact satisfies BetaMoon's wetness check.
extinguishesFire boolean Body contact clears fire.
ignitesEntities boolean Body contact sets an entity on fire.
contactDamage nonnegative integer Environmental damage after each contact interval.
contactIntervalTicks integer 5–200 Interval for damage from this fluid; defaults to 10.

Body contact selects movement by greatest intersecting volume. Eye contact selects breathing and camera behavior. Equal body coverage resolves by block coordinate and fluid key. Wetness applies if any touching fluid declares it; extinguishing happens before ignition when both are present. Damage is aggregated per entity and fluid, so several blocks of the same fluid do not multiply a hit. Leaving contact resets its damage timer. Contact checks sample at most 64 fluid cells per entity, so contact with very large entities is approximate.

The water preset supplies swimming, currents, drowning, wetness, and extinguishing. The lava preset supplies lava movement, ignition, and contact damage. neutral supplies none of those behaviors. Explicit fields can combine them independently, such as a swim-friendly fluid that does not cause drowning.

camera

The camera uses the fluid at its eye. fogColor is a 24-bit RGB integer; fogDensity is an exponential density from 0 to 1, with 0 disabling fluid fog. overlay accepts a registered texture reference, namespaced texture key, or relative PNG path using the asset rules. Set it to false to suppress the preset overlay. The water preset has water fog and an overlay; the lava preset has dense warm fog and no overlay; neutral has neither.

Fluid registration requires the BetaMoon Java agent. A requested camera effect raises a registration error if its required client support is unavailable. The overlay asset must resolve before registration.

blocks and bucket

Each blocks.flowing / blocks.still entry requires id and canonical block key; displayName is optional. IDs must be distinct unused values in 1–255, but do not need to be consecutive.

The optional bucket requires a shifted item id (at least 256), canonical item key, and either texture or icon = { x, y }; displayName is optional. It stacks to one and returns the vanilla empty bucket. Empty vanilla buckets collect only metadata-0 sources. Filled buckets place a flowing metadata-0 source. A water-preset bucket evaporates in the Nether with the vanilla fizz/smoke effect.

Using an empty vanilla bucket on a custom source which has no valid configured bucket leaves both the source and the empty bucket unchanged; it never falls through and converts the source into a vanilla water/lava bucket. Placement checks modification permission for both the selected block and the face-offset destination. A filled bucket returns the vanilla empty bucket only after placement succeeds or its configured Nether evaporation completes.

Advanced block and bucket registration

Use betamoon.fluids:define when block/item declarations need to be explicit. The returned token is unpublished and must be bound during the same registration pass.

local definition = betamoon.fluids:define {
    key = "my_mod:fluid/brine",
    material = betamoon.mc.blockMaterials.water,
    appearance = { still = 19, flowing = 20 }
}

local flowing = betamoon.blocks:add {
    type = "fluid", fluid = definition, fluidRole = "flowing",
    id = 181, key = "my_mod:block/brine_flowing"
}

local still = betamoon.blocks:add {
    type = "fluid", fluid = definition, fluidRole = "still",
    id = 189, key = "my_mod:block/brine_still"
}

local brine = definition:bind { flowing = flowing, still = still }

A specialized bucket uses type = "fluid_bucket", the same definition token, id, key, optional displayName, and texture or icon. Pass its returned item reference as bucket to bind. The specialized declarations reject ordinary block/item fields that would conflict with fluid-owned simulation and presentation.

An unbound definition is reported as a registration error and is never visible through fluid lookup.

Lookup and references

betamoon.fluids provides get, getRequired, find, first, and one.

local water = betamoon.fluids:getRequired("minecraft:fluid/water")
local waterMaterialFluids = betamoon.fluids:find {
    material = "water", isVanilla = false
}

get returns nil when missing; getRequired raises an error. find returns an ordinary array. first returns the first match or nil; one returns nil for none and errors for multiple matches. Query fields are key, material, preset, bucket, and isVanilla.

Fluid references expose key, owner, isVanilla, exists, material, preset, flowingBlock, stillBlock, and bucketItem (possibly nil). A fluid block reference also exposes fluid and fluidRole; a bucket item reference exposes fluid. The built-in minecraft:fluid/water and minecraft:fluid/lava references are read-only lookup entries.

Fluid interactions

betamoon.fluids.interactions:add(definition) declares deterministic contact results. fluids must contain exactly two distinct registered fluid references or keys. replace selects which one's cell changes.

betamoon.fluids.interactions:add {
    key = "my_mod:fluid_interaction/acid_water",
    fluids = { acid, "minecraft:fluid/water" },
    replace = acid,
    faces = { "north", "south", "east", "west", "up" },
    outcomes = {
        { when = { source = true }, replaceWith = "my_mod:block/acid_crystal" },
        { when = { source = false }, replaceWith = false }
    },
    effects = {
        sound = "random.fizz", volume = 0.5, pitch = 2.6,
        particle = "largesmoke", particleCount = 8
    }
}

faces defaults to all six cardinal faces. Outcomes are checked in order; when may filter source, falling, minLevel, and maxLevel. replaceWith must resolve to a registered non-fluid block, or be false for air. Omitting a matching clause leaves the fluid unchanged. Effects support sound, volume, pitch, particle, a bounded particleCount (0–64), and when = "changed" (default) or "contact".

Two rules cannot cover the same replacement fluid, counterpart, and face. Register separate non-overlapping face sets when multiple rules are required.

Vanilla lava-water contact follows Minecraft Beta behavior: a lava source becomes obsidian, non-falling levels 1–4 become cobblestone, water below does not trigger hardening, and the fizz/smoke effect still occurs for contact which does not replace deep or falling lava. This built-in rule is permanent and cannot be replaced by a script rule.

Runtime behavior

  • Flow tries downward first, then all equally short horizontal routes to a drop.
  • A stable flowing cell changes to its explicitly paired still block.
  • A neighbor change wakes a still cell without assuming adjacent IDs.
  • Source creation follows the selected policy and requires support below.
  • Rendering supports independent still and flowing textures.
  • Fluid cells have no collision box and can be ray-selected only when they are sources and liquid selection is active.
  • Current acceleration follows the selected entity.movement and currentScale policy.

Current compatibility limits

The material field accepts only water or lava. Some Minecraft and third-party behavior checks block material, so it may treat a custom fluid like the selected vanilla material. For example, a water-material fluid may affect boats, farmland, reeds, or sponges like water. Choose the material with those interactions in mind.

With the Java agent installed, vanilla lava-water hardening distinguishes registered vanilla water and lava from custom fluids. Define fluid interactions for custom combinations.

Still and flowing textures may each use the shared animated texture input, including one registered texture asset reused by both roles. Numeric atlas indices remain available.

Reload compatibility

Flow settings, appearance, displacement, entity and camera policies, and interaction rules can be changed on reload. Interaction rules omitted on reload are removed. Changing the fluid key, material, flowing/still block IDs and roles, bucket ID, or whether a bucket exists requires restarting Minecraft.

If a declaration disappears, its blocks and items remain registered until restart to protect loaded worlds and inventories. Keep numeric IDs and keys stable, and back up worlds before removing content.

Clone this wiki locally