Repository navigation
API 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
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.
| 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.
| 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.
| 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.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 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.
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.
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.
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.
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.
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.
- 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.movementandcurrentScalepolicy.
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.
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.
- Installation
- Install scripts
- Getting started
- VS Code and LuaLS
- Examples
- Reload and compatibility
- Troubleshooting
- Changelog
Scripts and shared values
- Script lifecycle
- Packaged Lua mods
- Modules
- References and stacks
- Queries
- Overrides
- Minecraft constants
- Chat and positions
- Structured data
- Script configuration
- Particles
Blocks and items
- Multiblocks
- Blocks
- Block state and placement
- Block shapes and rendering
- Block callbacks
- Block ticks and redstone
- Items
- Fluids
- Item callbacks
- Tools and armor
- Materials
- Textures
Entities
- Entities
- Entity access and movement
- Entity lifecycle and data
- Entity health and loot
- Entity inventories and relationships
- Projectiles and pickups
- Entity presentation and sounds
- Living entities and AI
- Entity parts and sensors
Assets and audio
- Assets
- Models and animations
- Built-in Minecraft models
- Model appearances
- Blockbench workflow
- Audio
- Texture-pack overrides
Events and world actions
World generation
World systems
Inventories and screens
Recipes