1
0
Fork 0

Compare commits

...

3 Commits

3 changed files with 678 additions and 751 deletions

124
API.md
View File

@ -54,7 +54,7 @@ under can do this.
Liquids can never be passed down to hardened dripstones.
3. If the dripstone is a spike size, it can release the droplet downwards to the
ground or to an object (such as a dripstone spike or a cauldron) that can catch
the droplet. If there's no surface within 25 blocks, the droplet evaporates. If
the droplet. If there's no surface within 50 blocks, the droplet evaporates. If
there's a surface that is unable to catch the droplet, a new spike will grow on
top, effectively forming a new stalagmite.
@ -85,17 +85,115 @@ Huge dripstone cannot be upgraded to a dripstone block, however.
## Lua modders
The following API functions are exposed for you to manipulate this mod with.
Everything until this section has been an introduction to how the mod has
implemented dripstone. However, you are welcome to make changes and add your
own types!
- `noordstar_dripstone.add_lava_source(nodename)` Add a node name that the mod
should consider a source of lava droplets above dripstone blocks.
- `noordstar_dripstone.add_water_source(nodename)` Add a node name that the mod
should consider a source of water droplets above dripstone blocks.
- `noordstar_dripstone.add_lava_catcher(oldnodename, newnodename)` Register a
node that can catch lava droplets to transform into a new node, such as a
cauldron.
- `noordstar_dripstone.add_water_catcher(oldnodename, newnodename)` Register a
node that can catch water droplets to transform into a new node, such as a
cauldron.
Matter of fact, everything until this section has been written using this
publicly available mod. So take a look at [the init.lua file](init.lua) if
you'd prefer to look at a real example.
All input values are strings in this API.
This mod uses **droplets** to build the dripstone. These are incredibly tiny
drops of liquid that flow down a dripstone. Currently, there are two
types in use: `water` and `lava`.
### noordstar_dripstone.register_droplet(droplet)
Every droplet type is a unique string. Different droplets interact uniquely
with different dripstones.
```lua
noordstar_dripstone.register_droplet("magma")
noordstar_dripstone.register_droplet("mercury")
noordstar_dripstone.register_droplet("mineral_water")
```
### noordstar_dripstone.add_droplet_source(droplet, nodename)
In order to let droplets stream down dripstone nodes, you need to define which
nodes a full dripstone block can absorb liquid from. Absorbing liquid does not
affect the liquid node: this mod creates a way for players to duplicate liquid
nodes.
Generally, you are recommended to use liquid source blocks to create droplets.
However, you don't need to do this! You could use any node, as long as it has a
name.
```lua
noordstar_dripstone.add_droplet_source("water", "mymod:swamp_water_source")
```
### noordstar_dripstone.add_droplet_catcher(droplet, oldnodename, newnodename)
Similarly, on the other side of the dripstone, you can create a catcher that
can catch any of the liquid drops dripping down. You can use this to create
orchids, or to create other interactions with nodes that might change from a
tiny bit of liquid.
```lua
noordstar_dripstone.add_droplet_catcher("water", "mymod:cauldron_empty", "mymod:water_cauldron")
noordstar_dripstone.add_droplet_catcher("water", "mymod:dirt", "mymod:farmland")
noordstar_dripstone.add_droplet_catcher("lava", "mymod:precious_orchid", "mymod:dead_bush")
```
### noordstar_dripstone.register_dripstone(flavor, def)
You can define your own dripstone type. You need to pick a flavor (which you
shouldn't namespace) and you need to offer a dripstone definition, which is
defined as follows:
```
{
-- What item is dropped when the dripstone is broken.
-- When left nil, the spike of the dripstone type is dropped.
drop = "dry"
-- What flavor to become when using liquid to grow.
-- Leave to nil when unable to grow.
grow_to = "dry"
-- When receiving a droplet of a given type, transform into a different
-- dripstone type. When a droplet is unspecified, the block cannot
-- receive the droplet.
on_droplet_receive = {
water = "watered",
lava = "molten",
}
-- Sounds that the dripstone makes
sounds = <standard sound definition for a node>
-- Node tiles for layout
tiles = <node tile layout>
-- Droplet type that the dripstone flavor can pass down.
-- When the droplet is passed down, the dripstone converts to the
-- "grow_to" type
trickle_down = "water"
-- Speed of how often a droplet trickles down.
trickle_speed = 5
}
```
For examples, refer to [this mod's init.lua file](init.lua).
### noordstar_dripstone.size_to_name(flavor, size)
Lastly, this function serves as a tool to help you find the node name of a
dripstone of a given flavor and size. Remember that dripstone size range from 1
to 8.
```lua
noordstar_dripstone.size_to_name("dry", 1)
-- Returns "noordstar_dripstone:dry_dripstone_spike"
noordstar_dripstone.size_to_name("lol", 3)
-- Returns "noordstar_dripstone:small_lol_dripstone"
noordstar_dripstone.size_to_name("cool", 8)
-- Returns "noordstar_dripstone:cool_dripstone_block"
```
Note how the function even returns a string if the dripstone type hasn't been
registered.

492
api.lua Normal file
View File

@ -0,0 +1,492 @@
noordstar_dripstone = {}
-- Internal values that cannot be changed by other mods (directly).
local internal = {
-- These values are not meant to be changed during runtime.
constant = {
-- How many nodes downwards a droplet is able to drop from a stalactite
-- before the droplet evaporates.
drop_down_reach = 50,
-- The number of seconds it takes for a dripstone node to grow 1 unit
-- (NOTE: Not one node size! One unit, which quadratically increases
-- per node size.)
growth_factor = 3,
-- This mod's name.
modname = minetest.get_current_modname(),
-- The number of samples that each ABM should execute.
-- Make sure this is a whole number and less than speed_factor.
samples_per_interval = 30,
-- Factor deciding this mod's relative speed.
-- Set this value to 1 if you wish to debug and let the dripstone
-- change rapidly.
-- Rule of thumb: with a setting of 60, it takes a lava farm about 30
-- minutes to fill a cauldron with lava.
speed_factor = 60,
-- Names of the various dripstone widths
width_names = {
"spike", "tiny", "small", "medium",
"great", "large", "huge", "block",
},
},
-- Nodes that function as cauldrons
cauldrons = {},
-- Nodes that provide droplets
sources = {},
-- Nodes that allow a droplet to trickle down if it is directly below a
-- node that passes down that droplet.
tricklers = {},
}
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
--------------------------- PUBLIC API --------------------------------
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-- Register a node that can catch a droplet from a dripstone stalactite.
function noordstar_dripstone.add_droplet_catcher(droplet, oldnodename, newnodename)
return internal.add_droplet_catcher(droplet, oldnodename, newnodename)
end
-- Register a new source node that can provide droplets to dripstone blocks.
function noordstar_dripstone.add_droplet_source(droplet, nodename)
return internal.add_droplet_source(droplet, nodename)
end
-- Register a new dripstone type.
--
-- {
-- -- What item is dropped when the dripstone is broken.
-- -- When left nil, the spike of the dripstone type is dropped.
-- drop = "dry"
--
-- -- What flavor to become when using liquid to grow.
-- -- Leave to nil when unable to grow.
-- grow_to = "dry"
--
-- -- When receiving a droplet of a given type, transform into a different
-- -- dripstone type. When a droplet is unspecified, the block cannot
-- -- receive the droplet.
-- on_droplet_receive = {
-- water = "watered",
-- lava = "molten",
-- }
--
-- -- Sounds that the dripstone makes
-- sounds = <standard sound definition for a node>
--
-- -- Node tiles for layout
-- tiles = <node tile layout>
--
-- -- Droplet type that the dripstone flavor can pass down.
-- -- When the droplet is passed down, the dripstone converts to the
-- -- "grow_to" type
-- trickle_down = "water"
--
-- -- Speed of how often a droplet trickles down.
-- trickle_speed = 5
-- }
function noordstar_dripstone.register_dripstone(flavor, def)
return internal.register_dripstone_flavor(flavor, def)
end
-- Register a new droplet type that can be absorbed and passed on by dripstone.
function noordstar_dripstone.register_droplet(droplet)
if internal.cauldrons[droplet] == nil then
internal.cauldrons[droplet] = {}
end
if internal.sources[droplet] == nil then
internal.sources[droplet] = {}
end
if internal.tricklers[droplet] == nil then
internal.tricklers[droplet] = {}
end
end
-- Get a dripstone's node name based on its flavor and size.
function noordstar_dripstone.size_to_name(flavor, size)
return internal.size_to_name(flavor, size)
end
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-- Add a droplet catcher, which is a node that allows a stalactite spike to
-- change the name using a droplet.
function internal.add_droplet_catcher(droplet, oldnodename, newnodename)
return internal.register_cauldron(droplet, oldnodename, newnodename)
end
function internal.add_droplet_source(droplet, nodename)
if internal.sources[droplet] == nil then
internal.uninitialized_droplet_error(droplet)
end
table.insert(internal.sources[droplet], nodename)
end
-- Add a droplet trickler, which is a dripstone node that allows a droplet to
-- be trickled down from the node directly above it.
-- Running this function overrides previous values.
function internal.add_droplet_trickler(droplet, oldnodename, newnodename)
if internal.tricklers[droplet] == nil then
internal.uninitialized_droplet_error(droplet)
end
internal.tricklers[droplet][oldnodename] = newnodename
end
-- Capitalize a string
function internal.capitalize(str)
return (str:gsub("^%l", string.upper))
end
function internal.drawtype_of_size(size)
if size >= 8 then
return "normal"
else
return "nodebox"
end
end
function internal.hit_with_droplet(pos, node, droplet, spikename)
local m = internal.cauldrons[droplet] or {}
if m[node.name] == nil then
-- Not a cauldron! Therefore we place a spike on top.
pos = vector.offset(pos, 0, 1, 0)
node = minetest.get_node(pos)
node.name = spikename
minetest.set_node(pos, node)
else
node.name = m[node.name]
minetest.set_node(pos, node)
end
end
-- Determine whether this mod considers a node an air node.
function internal.is_air(nodename)
if nodename == "air" then
return true
else
return minetest.get_item_group(nodename, "air") ~= 0
end
end
-- Create a node box for any given dripstone size.
-- Size 8 is a normal block size
function internal.nodebox_of_size(size)
if size >= 8 then
return nil
else
return {
type = "fixed",
fixed = {
{ - size / 16, -0.5, - size / 16, size / 16, 0.5, size / 16 },
},
}
end
end
function internal.register_absorb_abm(droplet, oldnodename, newnodename)
minetest.register_abm({
nodenames = { oldnodename },
interval = internal.constant.speed_factor / internal.constant.samples_per_interval,
chance = internal.constant.samples_per_interval,
catch_up = true,
action = function (pos, node, aoc, aocw)
local pos_above = vector.offset(pos, 0, 1, 0)
local node_above = minetest.get_node(pos_above)
for _, source in pairs(internal.sources[droplet] or {}) do
if node_above.name == source then
node.name = newnodename
minetest.set_node(pos, node)
return
end
end
end
})
end
function internal.register_cauldron(droplet, oldnodename, newnodename)
if internal.cauldrons[droplet] == nil then
internal.uninitialized_droplet_error(droplet)
end
internal.cauldrons[droplet][oldnodename] = newnodename
end
function internal.register_dripstone_craft(newnodename, oldnodename, spikename)
minetest.register_craft({
output = newnodename,
recipe = {
{ spikename, spikename , spikename },
{ spikename, oldnodename, spikename },
{ spikename, spikename , spikename },
}
})
end
function internal.register_dripstone_flavor(flavor, def)
-- Guaranteed values
local drop = def.drop or internal.size_to_name(flavor, 1)
local on_droplet_receive = def.on_droplet_receive or {}
local trickle_speed = def.trickle_speed or 1
-- Potentially nil, might need to be checked before assumed safe
local dry_up = def.grow_to
local sounds = def.sounds
local tiles = def.tiles
local trickl = def.trickle_down
-- Register nodes
for width = 1, 8, 1 do
internal.register_dripstone_node(flavor, width, tiles, sounds, drop)
end
-- Register upgrade crafting recipes
for width = 1, 6, 1 do
internal.register_dripstone_craft(
internal.size_to_name(flavor, width + 1),
internal.size_to_name(flavor, width),
internal.size_to_description(flavor, 1)
)
end
-- Allow dripstone nodes to trickle down droplets
for droplet, new_flavor in pairs(on_droplet_receive) do
for width = 1, 8, 1 do
internal.add_droplet_trickler(
droplet,
internal.size_to_name(flavor, width),
internal.size_to_name(new_flavor, width)
)
end
end
-- Allow spike stalagmites to catch droplets
for droplet, new_flavor in pairs(on_droplet_receive) do
internal.register_cauldron(
droplet,
internal.size_to_name(flavor, 1),
internal.size_to_name(new_flavor, 1)
)
end
-- Register ABM to grow when possible.
if dry_up then
for width = 1, 6, 1 do
internal.register_grow_abm(
internal.size_to_name(flavor, width),
internal.size_to_name(dry_up, width + 1),
width
)
end
end
-- Register ABM to grow when possible
if trickl and dry_up then
for width = 1, 8, 1 do
internal.register_trickle_down_abm(
trickl,
width,
internal.size_to_name(flavor, width),
internal.size_to_name(dry_up, width),
dry_up,
trickle_speed
)
end
end
-- Register ABM to absorb liquids from above
for droplet, new_flavor in pairs(on_droplet_receive) do
internal.register_absorb_abm(
droplet,
internal.size_to_name(flavor, 8),
internal.size_to_name(new_flavor, 8)
)
end
-- Register ABM to drop down droplets from a stalactite spike
if dry_up and trickl then
internal.register_drop_down_abm(
trickl,
internal.size_to_name(flavor, 1),
internal.size_to_name(dry_up, 1),
trickle_speed
)
-- Makes dripstone stalagmite spikes delete droplets.
-- Without this, stalactites remain very thick and short while
-- stalagmites become absurdly long and thin.
-- A watered stalagmite can't accept a water droplet and the stalagmite
-- therefore grows one per droplet. To mitigate this, a watered spike
-- can still act as a water droplet cauldron without changing.
-- This way, no new droplets are passed on if the stalagmite is already
-- full, and the structure simply waits for a dripstone node to grow.
-- This behaviour is designed to be easy to override. (For example: if
-- you want a HEAVY watered dripstone type that holds 2 droplets.)
internal.add_droplet_catcher(
trickl,
internal.size_to_name(flavor, 1),
internal.size_to_name(flavor, 1)
)
end
end
function internal.register_dripstone_node(flavor, size, tiles, sounds, drop)
minetest.register_node(internal.size_to_name(flavor, size), {
description = internal.size_to_description(flavor, size),
tiles = tiles,
groups = {
pickaxey=2,
material_stone=1,
fall_damage_add_percent = math.max(4 - size, 0) / 4 * 100
},
is_ground_content = true,
drop = {
max_items = math.floor((size + 1) / 2),
items = {
{ rarity = 1
, items = { drop }
},
{ rarity = 2
, items = { drop }
},
{ rarity = 4
, items = { drop }
},
{ rarity = 4
, items = { drop }
},
}
},
sounds = sounds,
drawtype = internal.drawtype_of_size(size),
paramtype = "light",
sunlight_propagates = size < 8,
node_box = internal.nodebox_of_size(size),
_mcl_hardness = 1.0 + size / 8,
_mcl_blast_resistance = 1 + size / 2,
_mcl_silk_touch_drop = true,
})
end
function internal.register_drop_down_abm(droplet, spikename, dryspikename, trickle_speed)
minetest.register_abm({
nodenames = { spikename },
interval = trickle_speed * internal.constant.speed_factor / internal.constant.samples_per_interval,
chance = internal.constant.samples_per_interval,
catch_up = true,
action = function (pos, node, aoc, aocw)
local pos_below = vector.offset(pos, 0, -1, 0)
local node_below = minetest.get_node(pos_below)
if not internal.is_air(node_below.name) then
-- Node below is not air! Unable to drop a droplet down.
return
end
for dy = 2, internal.constant.drop_down_reach, 1 do
pos_below = vector.offset(pos, 0, -dy, 0)
node_below = minetest.get_node(pos_below)
if not internal.is_air(node_below.name) then
-- Node is not air! If it is a cauldron, update the node.
internal.hit_with_droplet(
pos_below,
node_below,
droplet,
dryspikename
)
break
end
end
node.name = dryspikename
minetest.set_node(pos, node)
end
})
end
function internal.register_grow_abm(oldnodename, newnodename, width)
minetest.register_abm({
nodenames = { oldnodename },
-- 2(w + 1) * 2(w + 1) - 2w * 2w = 8w + 4
interval = (8 * width + 4) * internal.constant.speed_factor * internal.constant.growth_factor / internal.constant.samples_per_interval,
chance = internal.constant.samples_per_interval,
catch_up = true,
action = function (pos, node, aoc, aocw)
node.name = newnodename
minetest.set_node(pos, node)
end
})
end
function internal.register_trickle_down_abm(droplet, width, old_source, new_source, dry_up, trickle_speed)
minetest.register_abm({
nodenames = { old_source },
interval = trickle_speed * internal.constant.speed_factor / internal.constant.samples_per_interval,
chance = internal.constant.samples_per_interval,
catch_up = true,
action = function (pos, node, aoc, aocw)
local pos_below = vector.offset(pos, 0, -1, 0)
local node_below = minetest.get_node(pos_below)
local m = internal.tricklers[droplet] or {}
if m[node_below.name] ~= nil then
-- Trickler found below!
node_below.name = m[node_below.name]
elseif width > 1 and internal.is_air(node_below.name) then
-- Air node found below a non-spike, turn it into a spike.
node_below.name = internal.size_to_name(dry_up, 1)
else
return -- Prevent droplet from leaking away
end
node.name = new_source
minetest.set_node(pos_below, node_below)
minetest.set_node(pos, node)
end
})
end
function internal.size_to_description(flavor, size)
local width_name = internal.constant.width_names[size]
if size == 1 or size == 8 then
return internal.capitalize(flavor) .. " dripstone " .. width_name
else
return internal.capitalize(width_name) .. " " .. flavor .. " dripstone"
end
end
function internal.size_to_name(flavor, size)
local namespace = internal.constant.modname .. ":"
local width_name = internal.constant.width_names[size]
if size == 1 or size == 8 then
return namespace .. flavor .. "_dripstone_" .. width_name
else
return namespace .. width_name .. "_" .. flavor .. "_dripstone"
end
end
function internal.uninitialized_droplet_error(droplet)
error(
"Droplet " .. droplet .. " has not been initialized yet!"
)
end

813
init.lua
View File

@ -1,750 +1,87 @@
noordstar_dripstone = {}
-- Load dripstone API
-- Constants
local speed_factor = 30
local seconds_per_growth = 10 * speed_factor
local seconds_per_water_trickle = 1 * speed_factor
local seconds_per_lava_trickle = 6 * speed_factor
local samples_per_interval = 30
local modpath = minetest.get_modpath(minetest.get_current_modname())
-- Namespaced node names
local dry_dripstone_block = "noordstar_dripstone:dripstone_block"
local dry_dripstone_huge = "noordstar_dripstone:huge_dripstone"
local dry_dripstone_large = "noordstar_dripstone:large_dripstone"
local dry_dripstone_great = "noordstar_dripstone:great_dripstone"
local dry_dripstone_medium = "noordstar_dripstone:medium_dripstone"
local dry_dripstone_small = "noordstar_dripstone:small_dripstone"
local dry_dripstone_tiny = "noordstar_dripstone:tiny_dripstone"
local dry_dripstone_spike = "noordstar_dripstone:dripstone_spike"
local hardened_dripstone_block = "noordstar_dripstone:hardened_dripstone_block"
local hardened_dripstone_huge = "noordstar_dripstone:huge_hardened_dripstone"
local hardened_dripstone_large = "noordstar_dripstone:large_hardened_dripstone"
local hardened_dripstone_great = "noordstar_dripstone:great_hardened_dripstone"
local hardened_dripstone_medium = "noordstar_dripstone:medium_hardened_dripstone"
local hardened_dripstone_small = "noordstar_dripstone:small_hardened_dripstone"
local hardened_dripstone_tiny = "noordstar_dripstone:tiny_hardened_dripstone"
local hardened_dripstone_spike = "noordstar_dripstone:hardened_dripstone_spike"
local molten_dripstone_block = "noordstar_dripstone:molten_dripstone_block"
local molten_dripstone_huge = "noordstar_dripstone:huge_molten_dripstone"
local molten_dripstone_large = "noordstar_dripstone:large_molten_dripstone"
local molten_dripstone_great = "noordstar_dripstone:great_molten_dripstone"
local molten_dripstone_medium = "noordstar_dripstone:medium_molten_dripstone"
local molten_dripstone_small = "noordstar_dripstone:small_molten_dripstone"
local molten_dripstone_tiny = "noordstar_dripstone:tiny_molten_dripstone"
local molten_dripstone_spike = "noordstar_dripstone:molten_dripstone_spike"
local watered_dripstone_block = "noordstar_dripstone:watered_dripstone_block"
local watered_dripstone_huge = "noordstar_dripstone:huge_watered_dripstone"
local watered_dripstone_large = "noordstar_dripstone:large_watered_dripstone"
local watered_dripstone_great = "noordstar_dripstone:great_watered_dripstone"
local watered_dripstone_medium = "noordstar_dripstone:medium_watered_dripstone"
local watered_dripstone_small = "noordstar_dripstone:small_watered_dripstone"
local watered_dripstone_tiny = "noordstar_dripstone:tiny_watered_dripstone"
local watered_dripstone_spike = "noordstar_dripstone:watered_dripstone_spike"
local internal = {
-- Nodes that the mod should consider as sources to extract water from
water_nodes =
{ "default:river_water_source"
, "default:water_source"
, "mcl_core:water_source"
, "mclx_core:river_water_source"
},
-- Nodes that the mod should consider as sources to extract lava from
lava_nodes =
{ "default:lava_source"
, "mcl_core:lava_source"
},
-- Nodes that can catch a lava droplet instead of letting a spike grow on top
lava_cauldrons = {
{ from = dry_dripstone_spike, to = molten_dripstone_spike },
{ from = "mcl_cauldrons:cauldron", to = "mcl_cauldrons:cauldron_1_lava" },
{ from = "mcl_cauldrons:cauldron_1_lava", to = "mcl_cauldrons:cauldron_2_lava" },
{ from = "mcl_cauldrons:cauldron_2_lava", to = "mcl_cauldrons:cauldron_3_lava" },
},
-- Nodes that can catch a water droplet instead of letting a spike grow on top
water_cauldrons = {
{ from = dry_dripstone_spike, to = watered_dripstone_spike },
{ from = "mcl_cauldrons:cauldron", to = "mcl_cauldrons:cauldron_1" },
{ from = "mcl_cauldrons:cauldron_1", to = "mcl_cauldrons:cauldron_2" },
{ from = "mcl_cauldrons:cauldron_2", to = "mcl_cauldrons:cauldron_3" },
}
}
function noordstar_dripstone.add_lava_source(nodename)
table.insert(internal.lava_nodes)
end
function noordstar_dripstone.add_water_source(nodename)
table.insert(internal.water_nodes, nodename)
local function load(name)
dofile(modpath.."/"..name..".lua")
end
function noordstar_dripstone.add_lava_catcher(nodename, newnodename)
table.insert(internal.lava_cauldrons, { from = nodename, to = newnodename })
end
function noordstar_dripstone.add_water_catcher(nodename, newnodename)
table.insert(internal.water_cauldrons, { from = nodename, to = newnodename })
load("api")
-- Choose dripstone sounds
local dripstone_sounds
if minetest.get_modpath("mcl_sounds") then
dripstone_sounds = mcl_sounds.node_sound_stone_defaults()
end
-- Register droplet types
noordstar_dripstone.register_droplet("water")
noordstar_dripstone.register_droplet("lava")
-- Create a node box for any given dripstone size.
-- Size 8 is a normal block size
local function nodebox_of_size(size)
if size >= 8 then
return nil
else
return {
type = "fixed",
fixed = {
{ - size / 16, -0.5, - size / 16, size / 16, 0.5, size / 16 },
},
}
end
-- Register dripstone types
noordstar_dripstone.register_dripstone("dry", {
sounds = dripstone_sounds,
tiles = {
"noordstar_dripstone_dripstone_top.png",
"noordstar_dripstone_dripstone_top.png",
"noordstar_dripstone_dripstone_side.png",
},
on_droplet_receive = {
water = "watered",
lava = "molten",
},
})
noordstar_dripstone.register_dripstone("watered", {
drop = noordstar_dripstone.size_to_name("dry", 1),
grow_to = "dry",
on_droplet_receive = {
lava = "hardened",
},
sounds = dripstone_sounds,
tiles = {
"noordstar_dripstone_watered_dripstone_top.png",
"noordstar_dripstone_watered_dripstone_top.png",
"noordstar_dripstone_watered_dripstone_side.png",
},
trickle_down = "water",
})
noordstar_dripstone.register_dripstone("molten", {
drop = noordstar_dripstone.size_to_name("dry", 1),
grow_to = "dry",
on_droplet_receive = {
water = "hardened",
},
sounds = dripstone_sounds,
tiles = {
"noordstar_dripstone_molten_dripstone_top.png",
"noordstar_dripstone_molten_dripstone_top.png",
"noordstar_dripstone_molten_dripstone_side.png",
},
trickle_down = "lava",
trickle_speed = 6,
})
noordstar_dripstone.register_dripstone("hardened", {
sounds = dripstone_sounds,
tiles = {
"noordstar_dripstone_hardened_dripstone_top.png",
"noordstar_dripstone_hardened_dripstone_top.png",
"noordstar_dripstone_hardened_dripstone_side.png",
}
})
-- Register droplet sources above dripstone blocks
if minetest.get_modpath("default") then
noordstar_dripstone.add_droplet_source("water", "default:river_water_source")
noordstar_dripstone.add_droplet_source("water", "default:water_source")
noordstar_dripstone.add_droplet_source("lava", "default:lava_source")
end
local function nodebox_type(size)
if size >= 8 then
return "normal"
else
return "nodebox"
end
if minetest.get_modpath("mcl_core") then
noordstar_dripstone.add_droplet_source("water", "mcl_core:water_source")
noordstar_dripstone.add_droplet_source("lava", "mcl_core:lava_source")
end
-- Sounds
local dripstone_sounds = nil
if mcl_sounds then
dripstone_sounds = mcl_sounds.node_sound_stone_defaults()
if minetest.get_modpath("mclx_core") then
noordstar_dripstone.add_droplet_source("water", "mclx_core:river_water_source")
end
-- Trickle down config
local lava_trickle_down = {
{ from = dry_dripstone_block, to = molten_dripstone_block },
{ from = dry_dripstone_huge, to = molten_dripstone_huge },
{ from = dry_dripstone_large, to = molten_dripstone_large },
{ from = dry_dripstone_great, to = molten_dripstone_great },
{ from = dry_dripstone_medium, to = molten_dripstone_medium },
{ from = dry_dripstone_small, to = molten_dripstone_small },
{ from = dry_dripstone_tiny, to = molten_dripstone_tiny },
{ from = dry_dripstone_spike, to = molten_dripstone_spike },
{ from = watered_dripstone_block, to = hardened_dripstone_block },
{ from = watered_dripstone_huge, to = hardened_dripstone_huge },
{ from = watered_dripstone_large, to = hardened_dripstone_large },
{ from = watered_dripstone_great, to = hardened_dripstone_great },
{ from = watered_dripstone_medium, to = hardened_dripstone_medium },
{ from = watered_dripstone_small, to = hardened_dripstone_small },
{ from = watered_dripstone_tiny, to = hardened_dripstone_tiny },
{ from = watered_dripstone_spike, to = hardened_dripstone_spike },
{ from = "air", to = dry_dripstone_spike },
}
local water_trickle_down = {
{ from = dry_dripstone_block, to = watered_dripstone_block },
{ from = dry_dripstone_huge, to = watered_dripstone_huge },
{ from = dry_dripstone_large, to = watered_dripstone_large },
{ from = dry_dripstone_great, to = watered_dripstone_great },
{ from = dry_dripstone_medium, to = watered_dripstone_medium },
{ from = dry_dripstone_small, to = watered_dripstone_small },
{ from = dry_dripstone_tiny, to = watered_dripstone_tiny },
{ from = dry_dripstone_spike, to = watered_dripstone_spike },
{ from = molten_dripstone_block, to = hardened_dripstone_block },
{ from = molten_dripstone_huge, to = hardened_dripstone_huge },
{ from = molten_dripstone_large, to = hardened_dripstone_large },
{ from = molten_dripstone_great, to = hardened_dripstone_great },
{ from = molten_dripstone_medium, to = hardened_dripstone_medium },
{ from = molten_dripstone_small, to = hardened_dripstone_small },
{ from = molten_dripstone_tiny, to = hardened_dripstone_tiny },
{ from = molten_dripstone_spike, to = hardened_dripstone_spike },
{ from = "air", to = dry_dripstone_spike },
}
local lava_trickle_down_spike = {
{ from = dry_dripstone_block, to = molten_dripstone_block },
{ from = dry_dripstone_huge, to = molten_dripstone_huge },
{ from = dry_dripstone_large, to = molten_dripstone_large },
{ from = dry_dripstone_great, to = molten_dripstone_great },
{ from = dry_dripstone_medium, to = molten_dripstone_medium },
{ from = dry_dripstone_small, to = molten_dripstone_small },
{ from = dry_dripstone_tiny, to = molten_dripstone_tiny },
{ from = dry_dripstone_spike, to = molten_dripstone_spike },
{ from = watered_dripstone_block, to = hardened_dripstone_block },
{ from = watered_dripstone_huge, to = hardened_dripstone_huge },
{ from = watered_dripstone_large, to = hardened_dripstone_large },
{ from = watered_dripstone_great, to = hardened_dripstone_great },
{ from = watered_dripstone_medium, to = hardened_dripstone_medium },
{ from = watered_dripstone_small, to = hardened_dripstone_small },
{ from = watered_dripstone_tiny, to = hardened_dripstone_tiny },
{ from = watered_dripstone_spike, to = hardened_dripstone_spike },
}
local water_trickle_down_spike = {
{ from = dry_dripstone_block, to = watered_dripstone_block },
{ from = dry_dripstone_huge, to = watered_dripstone_huge },
{ from = dry_dripstone_large, to = watered_dripstone_large },
{ from = dry_dripstone_great, to = watered_dripstone_great },
{ from = dry_dripstone_medium, to = watered_dripstone_medium },
{ from = dry_dripstone_small, to = watered_dripstone_small },
{ from = dry_dripstone_tiny, to = watered_dripstone_tiny },
{ from = dry_dripstone_spike, to = watered_dripstone_spike },
{ from = molten_dripstone_block, to = hardened_dripstone_block },
{ from = molten_dripstone_huge, to = hardened_dripstone_huge },
{ from = molten_dripstone_large, to = hardened_dripstone_large },
{ from = molten_dripstone_great, to = hardened_dripstone_great },
{ from = molten_dripstone_medium, to = hardened_dripstone_medium },
{ from = molten_dripstone_small, to = hardened_dripstone_small },
{ from = molten_dripstone_tiny, to = hardened_dripstone_tiny },
{ from = molten_dripstone_spike, to = hardened_dripstone_spike },
}
-- Tiles for dripstone
local dry_dripstone_tiles =
{ "noordstar_dripstone_dripstone_top.png"
, "noordstar_dripstone_dripstone_top.png"
, "noordstar_dripstone_dripstone_side.png"
}
local hardened_dripstone_tiles =
{ "noordstar_dripstone_hardened_dripstone_top.png"
, "noordstar_dripstone_hardened_dripstone_top.png"
, "noordstar_dripstone_hardened_dripstone_side.png"
}
local molten_dripstone_tiles =
{ "noordstar_dripstone_molten_dripstone_top.png"
, "noordstar_dripstone_molten_dripstone_top.png"
, "noordstar_dripstone_molten_dripstone_side.png"
}
local watered_dripstone_tiles =
{ "noordstar_dripstone_watered_dripstone_top.png"
, "noordstar_dripstone_watered_dripstone_top.png"
, "noordstar_dripstone_watered_dripstone_side.png"
}
-- Register dripstone nodes
local function make_dripstone(name, desc, longdesc, tiles, drop, size)
local sunlight_propagates = nil
if size < 8 then
sunlight_propagates = true
end
minetest.register_node(name,
{ description = desc
, _doc_items_longdesc = longdesc
, tiles = tiles
, groups = { pickaxey=2, material_stone=1, fall_damage_add_percent = math.max(4 - size, 0) / 4 * 100 }
, is_ground_content = true
, drop = {
max_items = math.floor((size + 1) / 2),
items = {
{ rarity = 1
, items = { drop }
},
{ rarity = 2
, items = { drop }
},
{ rarity = 4
, items = { drop }
},
{ rarity = 4
, items = { drop }
},
}
}
, sounds = dripstone_sounds
, drawtype = nodebox_type(size)
, paramtype = "light"
, sunlight_propagates = sunlight_propagates
, node_box = nodebox_of_size(size)
, _mcl_hardness = 1.0 + size / 8
, _mcl_blast_resistance = 1 + size / 2
, _mcl_silk_touch_drop = true
}
)
end
-- BASE BLOCKS
-- These blocks are able to absorb water or lava from above them.
make_dripstone(
dry_dripstone_block,
"Dripstone block",
"Dripstone block that can suck up liquids above it and creates stalactites below it.",
dry_dripstone_tiles,
dry_dripstone_spike,
8
)
make_dripstone(
hardened_dripstone_block,
"Hardened dripstone block",
"Dripstone block that is no longer able to absorb liquids above it.",
hardened_dripstone_tiles,
dry_dripstone_spike,
8
)
make_dripstone(
molten_dripstone_block,
"Molten dripstone block",
"A dripstone block that has absorbed some lava, allowing it to form a stalactite.",
molten_dripstone_tiles,
dry_dripstone_spike,
8
)
make_dripstone(
watered_dripstone_block,
"Watered dripstone block",
"A dripstone block that has absorbed some water, allowing it to form a stalactite.",
watered_dripstone_tiles,
dry_dripstone_spike,
8
)
-- HUGE DRIPSTONE
-- This is the largest form a non-block can get.
make_dripstone(
dry_dripstone_huge,
"Huge dripstone",
"Dripstone in the largest shape it can reach.",
dry_dripstone_tiles,
dry_dripstone_spike,
7
)
make_dripstone(
hardened_dripstone_huge,
"Huge hardened dripstone",
"Dripstone in the largest shape it can reach. It is no longer able to grow or absorb liquids.",
hardened_dripstone_tiles,
hardened_dripstone_spike,
7
)
make_dripstone(
molten_dripstone_huge,
"Huge molten dripstone",
"Dripstone in the largest shape it can reach. It has absorbed some lava, but it can no longer grow in thickness.",
molten_dripstone_tiles,
dry_dripstone_spike,
7
)
make_dripstone(
watered_dripstone_huge,
"Huge watered dripstone",
"Dripstone in the largest shape it can reach. It has absorbed some water, but it can no longer grow in thickness.",
watered_dripstone_tiles,
dry_dripstone_spike,
7
)
-- LARGE DRIPSTONE
make_dripstone(
dry_dripstone_large,
"Large dripstone",
"A thick layer of dripstone.",
dry_dripstone_tiles,
dry_dripstone_spike,
6
)
make_dripstone(
hardened_dripstone_large,
"Large hardened dripstone",
"A thick layer of dripstone. It is no longer able to grow or absorb liquids.",
hardened_dripstone_tiles,
hardened_dripstone_spike,
6
)
make_dripstone(
molten_dripstone_large,
"Large molten dripstone",
"A thick layer of dripstone. It has absorbed some lava, so it is able to grow in thickness.",
molten_dripstone_tiles,
dry_dripstone_spike,
6
)
make_dripstone(
watered_dripstone_large,
"Large watered dripstone",
"A thick layer of dripstone. It has absorbed some water, so it is able to grow in thickness.",
watered_dripstone_tiles,
dry_dripstone_spike,
6
)
-- GREAT DRIPSTONE
make_dripstone(
dry_dripstone_great,
"Great dripstone",
"A thick layer of dripstone.",
dry_dripstone_tiles,
dry_dripstone_spike,
5
)
make_dripstone(
hardened_dripstone_great,
"Great hardened dripstone",
"A thick layer of dripstone. It is no longer able to grow or absorb liquids.",
hardened_dripstone_tiles,
hardened_dripstone_spike,
5
)
make_dripstone(
molten_dripstone_great,
"Great molten dripstone",
"A thick layer of dripstone. It has absorbed some lava, so it is able to grow in thickness.",
molten_dripstone_tiles,
dry_dripstone_spike,
5
)
make_dripstone(
watered_dripstone_great,
"Great watered dripstone",
"A thick layer of dripstone. It has absorbed some water, so it is able to grow in thickness.",
watered_dripstone_tiles,
dry_dripstone_spike,
5
)
-- MEDIUM DRIPSTONE
make_dripstone(
dry_dripstone_medium,
"Medium dripstone",
"A thick layer of dripstone.",
dry_dripstone_tiles,
dry_dripstone_spike,
4
)
make_dripstone(
hardened_dripstone_medium,
"Medium hardened dripstone",
"A thick layer of dripstone. It is no longer able to grow or absorb liquids.",
hardened_dripstone_tiles,
hardened_dripstone_spike,
4
)
make_dripstone(
molten_dripstone_medium,
"Medium molten dripstone",
"A thick layer of dripstone. It has absorbed some lava, so it is able to grow in thickness.",
molten_dripstone_tiles,
dry_dripstone_spike,
4
)
make_dripstone(
watered_dripstone_medium,
"Medium watered dripstone",
"A thick layer of dripstone. It has absorbed some water, so it is able to grow in thickness.",
watered_dripstone_tiles,
dry_dripstone_spike,
4
)
-- SMALL DRIPSTONE
make_dripstone(
dry_dripstone_small,
"Small dripstone",
"A thick layer of dripstone.",
dry_dripstone_tiles,
dry_dripstone_spike,
3
)
make_dripstone(
hardened_dripstone_small,
"Small hardened dripstone",
"A thick layer of dripstone. It is no longer able to grow or absorb liquids.",
hardened_dripstone_tiles,
hardened_dripstone_spike,
3
)
make_dripstone(
molten_dripstone_small,
"Small molten dripstone",
"A thick layer of dripstone. It has absorbed some lava, so it is able to grow in thickness.",
molten_dripstone_tiles,
dry_dripstone_spike,
3
)
make_dripstone(
watered_dripstone_small,
"Small watered dripstone",
"A thick layer of dripstone. It has absorbed some water, so it is able to grow in thickness.",
watered_dripstone_tiles,
dry_dripstone_spike,
3
)
-- TINY DRIPSTONE
make_dripstone(
dry_dripstone_tiny,
"Tiny dripstone",
"A thick layer of dripstone.",
dry_dripstone_tiles,
dry_dripstone_spike,
2
)
make_dripstone(
hardened_dripstone_tiny,
"Tiny hardened dripstone",
"A thick layer of dripstone. It is no longer able to grow or absorb liquids.",
hardened_dripstone_tiles,
hardened_dripstone_spike,
2
)
make_dripstone(
molten_dripstone_tiny,
"Tiny molten dripstone",
"A thick layer of dripstone. It has absorbed some lava, so it is able to grow in thickness.",
molten_dripstone_tiles,
dry_dripstone_spike,
2
)
make_dripstone(
watered_dripstone_tiny,
"Tiny watered dripstone",
"A thick layer of dripstone. It has absorbed some water, so it is able to grow in thickness.",
watered_dripstone_tiles,
dry_dripstone_spike,
2
)
-- DRIPSTONE SPIKE
make_dripstone(
dry_dripstone_spike,
"Dripstone spike",
"A thick layer of dripstone.",
dry_dripstone_tiles,
dry_dripstone_spike,
1
)
make_dripstone(
hardened_dripstone_spike,
"Hardened dripstone spike",
"A thick layer of dripstone. It is no longer able to grow or absorb liquids.",
hardened_dripstone_tiles,
hardened_dripstone_spike,
1
)
make_dripstone(
molten_dripstone_spike,
"Molten dripstone spike",
"A thick layer of dripstone. It has absorbed some lava, so it is able to grow in thickness.",
molten_dripstone_tiles,
dry_dripstone_spike,
1
)
make_dripstone(
watered_dripstone_spike,
"Watered dripstone spike",
"A thick layer of dripstone. It has absorbed some water, so it is able to grow in thickness.",
watered_dripstone_tiles,
dry_dripstone_spike,
1
)
-- ACTIONS
local function absorb_liquid(pos, node, aoc, aocw)
local node_above = minetest.get_node({ x = pos.x, y = pos.y + 1, z = pos.z }) or {}
local na_name = node_above.name
for _, water in pairs(noordstar_dripstone.water_nodes) do
if water == na_name then
-- Make block watery
node.name = watered_dripstone_block
minetest.set_node(pos, node)
return
end
end
for _, lava in pairs(noordstar_dripstone.lava_nodes) do
if lava == na_name then
-- Make block molten
node.name = molten_dripstone_block
minetest.set_node(pos, node)
return
end
end
end
local function drop_down_to(options, dry_up_node_name)
return function(pos, node, aoc, aocw)
for i = 1, 25 do
local pos_rel = { x = pos.x, y = pos.y - i, z = pos.z }
local node_rel = minetest.get_node(pos_rel) or {}
local node_name = node_rel.name or ""
if node_name == "air" then
else
-- Non-air node has been found!
-- Check if it reacts to the dripstone and if it can be
-- activated.
for _, option in pairs(options) do
if node_name == option.from then
node_rel.name = option.to
node.name = dry_up_node_name
minetest.set_node(pos, node)
minetest.set_node(pos_rel, node_rel)
return
end
end
-- The node cannot be changed and hence a new spike starts on top
-- of it.
if i > 1 then
pos_rel = { x = pos.x, y = pos.y - i + 1, z = pos.z }
minetest.set_node(pos_rel, { name = dry_dripstone_spike })
node.name = dry_up_node_name
minetest.set_node(pos, node)
end
return
end
end
end
end
local function grow_to(dry_grown_node_name)
return function(pos, node, aoc, aocw)
node.name = dry_grown_node_name
minetest.set_node(pos, node)
end
end
local function harden(harden_nodes_func)
return function(pos, node, aoc, aocw)
local node_above = minetest.get_node({ x = pos.x, y = pos.y + 1, z = pos.z }) or {}
local na_name = node_above.name
for _, hardener in pairs(harden_nodes_func()) do
if hardener == na_name then
-- Harden dripstone block
node.name = hardened_dripstone_block
minetest.set_node(pos, node)
return
end
end
end
end
local function trickle_down(options, dry_up_node_name)
return function(pos, node, aoc, aocw)
local pos_below = { x = pos.x, y = pos.y - 1, z = pos.z }
local node_below = minetest.get_node(pos_below) or {}
local nb_name = node_below.name or ""
for _, option in pairs(options) do
local expected_node_name = option.from or nil
local resulted_node_name = option.to
if nb_name == expected_node_name then
node.name = dry_up_node_name
node_below.name = resulted_node_name
minetest.set_node(pos, node)
minetest.set_node(pos_below, node_below)
return
end
end
end
end
local function make_abm(nodename, expected_duration, action)
minetest.register_abm(
{ nodenames = { nodename }
, interval = expected_duration / samples_per_interval
, chance = samples_per_interval
, catch_up = true
, action = action
}
)
end
-- ABSORB LIQUIDS
make_abm(dry_dripstone_block, seconds_per_water_trickle, absorb_liquid)
make_abm(molten_dripstone_block, seconds_per_lava_trickle, harden(function ()
return noordstar_dripstone.water_nodes
end))
make_abm(watered_dripstone_block, seconds_per_water_trickle, harden(function ()
return noordstar_dripstone.lava_nodes
end))
-- TRICKLE DOWN
make_abm(molten_dripstone_block, seconds_per_lava_trickle, trickle_down(lava_trickle_down, dry_dripstone_block))
make_abm(watered_dripstone_block, seconds_per_water_trickle, trickle_down(water_trickle_down, dry_dripstone_block))
make_abm(molten_dripstone_huge, seconds_per_lava_trickle, trickle_down(lava_trickle_down, dry_dripstone_huge))
make_abm(watered_dripstone_huge, seconds_per_water_trickle, trickle_down(water_trickle_down, dry_dripstone_huge))
make_abm(molten_dripstone_large, seconds_per_lava_trickle, trickle_down(lava_trickle_down, dry_dripstone_large))
make_abm(watered_dripstone_large, seconds_per_water_trickle, trickle_down(water_trickle_down, dry_dripstone_large))
make_abm(molten_dripstone_great, seconds_per_lava_trickle, trickle_down(lava_trickle_down, dry_dripstone_great))
make_abm(watered_dripstone_great, seconds_per_water_trickle, trickle_down(water_trickle_down, dry_dripstone_great))
make_abm(molten_dripstone_medium, seconds_per_lava_trickle, trickle_down(lava_trickle_down, dry_dripstone_medium))
make_abm(watered_dripstone_medium, seconds_per_water_trickle, trickle_down(water_trickle_down, dry_dripstone_medium))
make_abm(molten_dripstone_small, seconds_per_lava_trickle, trickle_down(lava_trickle_down, dry_dripstone_small))
make_abm(watered_dripstone_small, seconds_per_water_trickle, trickle_down(water_trickle_down, dry_dripstone_small))
make_abm(molten_dripstone_tiny, seconds_per_lava_trickle, trickle_down(lava_trickle_down, dry_dripstone_tiny))
make_abm(watered_dripstone_tiny, seconds_per_water_trickle, trickle_down(water_trickle_down, dry_dripstone_tiny))
make_abm(molten_dripstone_spike, seconds_per_lava_trickle, trickle_down(lava_trickle_down_spike, dry_dripstone_spike))
make_abm(watered_dripstone_spike, seconds_per_water_trickle, trickle_down(water_trickle_down_spike, dry_dripstone_spike))
-- GROW
make_abm(molten_dripstone_large, seconds_per_growth*(14*14 - 12*12), grow_to(dry_dripstone_huge))
make_abm(watered_dripstone_large, seconds_per_growth*(14*14 - 12*12), grow_to(dry_dripstone_huge))
make_abm(molten_dripstone_great, seconds_per_growth*(12*12 - 10*10), grow_to(dry_dripstone_large))
make_abm(watered_dripstone_great, seconds_per_growth*(12*12 - 10*10), grow_to(dry_dripstone_large))
make_abm(molten_dripstone_medium, seconds_per_growth*(10*10 - 8*8), grow_to(dry_dripstone_great))
make_abm(watered_dripstone_medium, seconds_per_growth*(10*10 - 8*8), grow_to(dry_dripstone_great))
make_abm(molten_dripstone_small, seconds_per_growth*(8*8 - 6*6), grow_to(dry_dripstone_medium))
make_abm(watered_dripstone_small, seconds_per_growth*(8*8 - 6*6), grow_to(dry_dripstone_medium))
make_abm(molten_dripstone_tiny, seconds_per_growth*(6*6 - 4*4), grow_to(dry_dripstone_small))
make_abm(watered_dripstone_tiny, seconds_per_growth*(6*6 - 4*4), grow_to(dry_dripstone_small))
make_abm(molten_dripstone_spike, seconds_per_growth*(4*4 - 2*2), grow_to(dry_dripstone_tiny))
make_abm(watered_dripstone_spike, seconds_per_growth*(4*4 - 2*2), grow_to(dry_dripstone_tiny))
-- DROP DOWN
make_abm(molten_dripstone_spike, seconds_per_lava_trickle, drop_down_to(lava_drop_down, dry_dripstone_spike))
make_abm(watered_dripstone_spike, seconds_per_water_trickle, drop_down_to(water_drop_down, dry_dripstone_spike))
-- CRATING RECIPES
local function gapple_recipe(gold, apple, gapple)
minetest.register_craft({
output = gapple,
recipe = {
{ gold, gold, gold },
{ gold, apple, gold },
{ gold, gold, gold },
}
})
end
gapple_recipe(dry_dripstone_spike, dry_dripstone_spike, dry_dripstone_tiny)
gapple_recipe(dry_dripstone_spike, dry_dripstone_tiny, dry_dripstone_small)
gapple_recipe(dry_dripstone_spike, dry_dripstone_small, dry_dripstone_medium)
gapple_recipe(dry_dripstone_spike, dry_dripstone_medium, dry_dripstone_great)
gapple_recipe(dry_dripstone_spike, dry_dripstone_great, dry_dripstone_large)
gapple_recipe(dry_dripstone_spike, dry_dripstone_large, dry_dripstone_huge)
gapple_recipe(hardened_dripstone_spike, hardened_dripstone_spike, hardened_dripstone_tiny)
gapple_recipe(hardened_dripstone_spike, hardened_dripstone_tiny, hardened_dripstone_small)
gapple_recipe(hardened_dripstone_spike, hardened_dripstone_small, hardened_dripstone_medium)
gapple_recipe(hardened_dripstone_spike, hardened_dripstone_medium, hardened_dripstone_great)
gapple_recipe(hardened_dripstone_spike, hardened_dripstone_great, hardened_dripstone_large)
gapple_recipe(hardened_dripstone_spike, hardened_dripstone_large, hardened_dripstone_huge)
gapple_recipe(molten_dripstone_spike, molten_dripstone_spike, molten_dripstone_tiny)
gapple_recipe(molten_dripstone_spike, molten_dripstone_tiny, molten_dripstone_small)
gapple_recipe(molten_dripstone_spike, molten_dripstone_small, molten_dripstone_medium)
gapple_recipe(molten_dripstone_spike, molten_dripstone_medium, molten_dripstone_great)
gapple_recipe(molten_dripstone_spike, molten_dripstone_great, molten_dripstone_large)
gapple_recipe(molten_dripstone_spike, molten_dripstone_large, molten_dripstone_huge)
gapple_recipe(watered_dripstone_spike, watered_dripstone_spike, watered_dripstone_tiny)
gapple_recipe(watered_dripstone_spike, watered_dripstone_tiny, watered_dripstone_small)
gapple_recipe(watered_dripstone_spike, watered_dripstone_small, watered_dripstone_medium)
gapple_recipe(watered_dripstone_spike, watered_dripstone_medium, watered_dripstone_great)
gapple_recipe(watered_dripstone_spike, watered_dripstone_great, watered_dripstone_large)
gapple_recipe(watered_dripstone_spike, watered_dripstone_large, watered_dripstone_huge)