forked from VoxeLibre/VoxeLibre
Compare commits
108 Commits
master
...
PhaethonH/
Author | SHA1 | Date |
---|---|---|
Phaethon H | 874d5986f6 | |
Phaethon H | 7ac3ffd0fe | |
Phaethon H | c08c98e74a | |
Phaethon H | c9d5bbbde3 | |
Phaethon H | a8d5d4fd55 | |
Phaethon H | 34c6aa1442 | |
Phaethon H | 1c9012c3ef | |
Phaethon H | b435bcbd5a | |
Phaethon H | 92b03acd35 | |
Phaethon H | 4c9c770405 | |
Phaethon H | 3a68e96ffe | |
Phaethon H | 07d9ae98d9 | |
Phaethon H | 02e905eb51 | |
Phaethon H | daa9354d32 | |
Phaethon H | a72359af4d | |
Phaethon H | cc35ebede0 | |
Phaethon H | 4e6f06619b | |
Phaethon H | c43223ad59 | |
Phaethon H | c0dea55862 | |
Phaethon H | 2f9fea5a5c | |
Phaethon H | 9d69f7e9e4 | |
Phaethon H | 9b0178f9c0 | |
Phaethon H | 11ce6c70e9 | |
Phaethon H | 88d95cd87d | |
Phaethon H | f7c0848163 | |
Phaethon H | f4b9bc379b | |
Phaethon H | 8271397f48 | |
Phaethon H | aa4fbcffa2 | |
Phaethon H | ceee755bab | |
Phaethon H | 34eff4a6a7 | |
Phaethon H | 5a0cad372f | |
iliekprogrammar | f61143758e | |
Phaethon H | 09d6174cf6 | |
Phaethon H | 0df6e4c57b | |
Phaethon H | 47ca9e76b7 | |
Phaethon H | b3797ce5de | |
Phaethon H | ea16d7cdf3 | |
iliekprogrammar | fa22ec4dd0 | |
Lizzy Fleckenstein | a7bc460fae | |
Phaethon H | dddf4912bd | |
Phaethon H | 5177a955f5 | |
iliekprogrammar | 0491b814dd | |
NO11 | 51dffc6c53 | |
NO11 | 30ce6f8a77 | |
Lizzy Fleckenstein | a34ae040c8 | |
Lizzy Fleckenstein | a410a7fabe | |
Phaethon H | 4f521903c0 | |
Phaethon H | 507e907c77 | |
Phaethon H | 6874591951 | |
Lizzy Fleckenstein | ea46c8741b | |
Phaethon H | 7ac997d33d | |
Phaethon H | 4a1d037590 | |
Phaethon H | 05a9968081 | |
Phaethon H | 91fe85fd1b | |
NO11 | 5b52deaa8a | |
NO11 | 7bbc1e9951 | |
Lizzy Fleckenstein | 0dd780ee2a | |
NO11 | 1b259f928b | |
Phaethon H | 48eb27655a | |
Phaethon H | a3de5b7cb0 | |
Phaethon H | 5b03c604b3 | |
Phaethon H | 407903b73a | |
Lizzy Fleckenstein | 970988cb39 | |
Lizzy Fleckenstein | 34f329a9d5 | |
Phaethon H | 6131f941b7 | |
Phaethon H | ad46840fa9 | |
Phaethon H | 3b9c553b6c | |
Phaethon H | 6ed5865aff | |
Phaethon H | fd8182c74c | |
Phaethon H | 2775f89979 | |
AFCMS | 1b0b5fc733 | |
AFCMS | 246ece7440 | |
AFCMS | 5c078b3d7b | |
AFCMS | 3fddffb942 | |
AFCMS | 225650904c | |
AFCMS | 1b144d507d | |
AFCMS | 738519f0a4 | |
AFCMS | d1ca012ea0 | |
AFCMS | a18a2127c5 | |
AFCMS | 7156afcd03 | |
AFCMS | e3b3e2343b | |
AFCMS | 6f23351126 | |
AFCMS | a99619774d | |
AFCMS | 989384f362 | |
AFCMS | 69da355f96 | |
AFCMS | 297d4e707c | |
AFCMS | b4033ddfc9 | |
AFCMS | c35c8a1713 | |
AFCMS | 64b49ba719 | |
AFCMS | d00490c86f | |
AFCMS | 8c91d23eb8 | |
AFCMS | 294cb3eb7d | |
AFCMS | cf4d57e584 | |
AFCMS | 890b95bb49 | |
AFCMS | 8611d27f1d | |
AFCMS | 59892abf6d | |
AFCMS | e69365f44d | |
AFCMS | aa0c7bd2cf | |
AFCMS | 2b73c16c69 | |
AFCMS | 36f479b2ec | |
AFCMS | 717a18ef16 | |
AFCMS | 9b0c87dabc | |
AFCMS | 3c83898095 | |
AFCMS | 6ebae965f6 | |
AFCMS | 5e5b3ebf75 | |
AFCMS | e68736a040 | |
AFCMS | 72149a2c56 | |
AFCMS | 182e825303 |
|
@ -32,6 +32,8 @@ playerbase on low spec computers, optimizations are hard to investigate.
|
|||
* [Matrix](https://app.element.io/#/room/#mc2:matrix.org)
|
||||
* [Reddit](https://www.reddit.com/r/MineClone2/)
|
||||
* [Minetest forums](https://forum.minetest.net/viewtopic.php?f=50&t=16407)
|
||||
* [ContentDB](https://content.minetest.net/packages/wuzzy/mineclone2/)
|
||||
* [OpenCollective](https://opencollective.com/mineclone2)
|
||||
|
||||
## Using git
|
||||
MineClone2 is developed using the version control system
|
||||
|
@ -194,9 +196,16 @@ MeseHub, let us know what you think about a topic and help us make
|
|||
decisions. Also, note that a lot of discussion takes place on the
|
||||
Discord server, so it's definitely worth checking it out.
|
||||
|
||||
### Funding
|
||||
You can help pay for our infrastructure (Mesehub) by donating to our
|
||||
OpenCollective link (See Links section).
|
||||
|
||||
### Crediting
|
||||
If you opened or have contributed to an issue, you receive the
|
||||
`Community` role on our Discord (after asking for it).
|
||||
OpenCollective Funders are credited in their own section in
|
||||
`CREDITS.md` and receive a special role "Funder" on our discord (unless
|
||||
they have made their donation Incognito).
|
||||
|
||||
## How you can help as a programmer
|
||||
(Almost) all the MineClone2 development is done using pull requests.
|
||||
|
|
|
@ -130,6 +130,9 @@
|
|||
* todoporlalibertad
|
||||
* Marcin Serwin
|
||||
|
||||
## Funders
|
||||
* 40W
|
||||
|
||||
## Special thanks
|
||||
* celeron55 for creating Minetest
|
||||
* Jordach for the jukebox music compilation from Big Freaking Dig
|
||||
|
|
|
@ -85,6 +85,8 @@ The MineClone2 repository is hosted at Mesehub. To contribute or report issues,
|
|||
* Matrix: <https://app.element.io/#/room/#mc2:matrix.org>
|
||||
* Reddit: <https://www.reddit.com/r/MineClone2/>
|
||||
* Minetest forums: <https://forum.minetest.net/viewtopic.php?f=50&t=16407>
|
||||
* ContentDB: <https://content.minetest.net/packages/wuzzy/mineclone2/>
|
||||
* OpenCollective: <https://opencollective.com/mineclone2>
|
||||
|
||||
## Target
|
||||
- Crucially, create a stable, moddable, free/libre clone of Minecraft
|
||||
|
|
|
@ -1,5 +1,27 @@
|
|||
mcl_util = {}
|
||||
|
||||
-- Updates all values in t using values from to*.
|
||||
function table.update(t, ...)
|
||||
for _, to in ipairs{...} do
|
||||
for k,v in pairs(to) do
|
||||
t[k] = v
|
||||
end
|
||||
end
|
||||
return t
|
||||
end
|
||||
|
||||
-- Updates nil values in t using values from to*.
|
||||
function table.update_nil(t, ...)
|
||||
for _, to in ipairs{...} do
|
||||
for k,v in pairs(to) do
|
||||
if t[k] == nil then
|
||||
t[k] = v
|
||||
end
|
||||
end
|
||||
end
|
||||
return t
|
||||
end
|
||||
|
||||
-- Based on minetest.rotate_and_place
|
||||
|
||||
--[[
|
||||
|
|
|
@ -12,7 +12,7 @@ Params:
|
|||
|
||||
* pos: position
|
||||
|
||||
## mcl_worlds.y_to_layer(y)
|
||||
## mcl_worlds.y_to_layer(y)
|
||||
This function is used to calculate the minetest y layer and dimension of the given <y> minecraft layer.
|
||||
Mainly used for ore generation.
|
||||
Takes an Y coordinate as input and returns:
|
||||
|
|
|
@ -115,7 +115,7 @@ local boat = {
|
|||
collisionbox = {-0.5, -0.35, -0.5, 0.5, 0.3, 0.5},
|
||||
visual = "mesh",
|
||||
mesh = "mcl_boats_boat.b3d",
|
||||
textures = {"mcl_boats_texture_oak_boat.png"},
|
||||
textures = {"mcl_boats_texture_oak_boat.png", "mcl_boats_texture_oak_boat.png", "mcl_boats_texture_oak_boat.png", "mcl_boats_texture_oak_boat.png", "mcl_boats_texture_oak_boat.png"},
|
||||
visual_size = boat_visual_size,
|
||||
hp_max = boat_max_hp,
|
||||
damage_texture_modifier = "^[colorize:white:0",
|
||||
|
@ -148,6 +148,11 @@ function boat.on_activate(self, staticdata, dtime_s)
|
|||
self._v = data.v
|
||||
self._last_v = self._v
|
||||
self._itemstring = data.itemstring
|
||||
|
||||
while #data.textures < 5 do
|
||||
table.insert(data.textures, data.textures[1])
|
||||
end
|
||||
|
||||
self.object:set_properties({textures = data.textures})
|
||||
end
|
||||
end
|
||||
|
@ -434,8 +439,9 @@ for b=1, #boat_ids do
|
|||
pos = vector.add(pos, vector.multiply(dir, boat_y_offset_ground))
|
||||
end
|
||||
local boat = minetest.add_entity(pos, "mcl_boats:boat")
|
||||
local texture = "mcl_boats_texture_"..images[b].."_boat.png"
|
||||
boat:get_luaentity()._itemstring = itemstring
|
||||
boat:set_properties({textures = { "mcl_boats_texture_"..images[b].."_boat.png" }})
|
||||
boat:set_properties({textures = { texture, texture, texture, texture, texture }})
|
||||
boat:set_yaw(placer:get_look_horizontal())
|
||||
if not minetest.is_creative_enabled(placer:get_player_name()) then
|
||||
itemstack:take_item()
|
||||
|
|
|
@ -228,22 +228,20 @@ if mcl_weather.allow_abm then
|
|||
-- Slowly fill up cauldrons
|
||||
minetest.register_abm({
|
||||
label = "Rain fills cauldrons with water",
|
||||
nodenames = {"mcl_cauldrons:cauldron", "mcl_cauldrons:cauldron_1", "mcl_cauldrons:cauldron_2"},
|
||||
nodenames = {"group:cauldron"},
|
||||
interval = 56.0,
|
||||
chance = 1,
|
||||
action = function(pos, node, active_object_count, active_object_count_wider)
|
||||
-- Rain is equivalent to a water bottle
|
||||
if mcl_weather.rain.raining and mcl_weather.is_outdoor(pos) then
|
||||
if node.name == "mcl_cauldrons:cauldron" then
|
||||
minetest.set_node(pos, {name="mcl_cauldrons:cauldron_1"})
|
||||
elseif node.name == "mcl_cauldrons:cauldron_1" then
|
||||
minetest.set_node(pos, {name="mcl_cauldrons:cauldron_2"})
|
||||
elseif node.name == "mcl_cauldrons:cauldron_2" then
|
||||
minetest.set_node(pos, {name="mcl_cauldrons:cauldron_3"})
|
||||
elseif node.name == "mcl_cauldrons:cauldron_1r" then
|
||||
minetest.set_node(pos, {name="mcl_cauldrons:cauldron_2r"})
|
||||
elseif node.name == "mcl_cauldrons:cauldron_2r" then
|
||||
minetest.set_node(pos, {name="mcl_cauldrons:cauldron_3r"})
|
||||
local newnode
|
||||
if mcl_cauldrons.is_cauldron(node) then
|
||||
if mcl_cauldrons.is_empty(node) or mcl_cauldrons.has_substance(node, "cauldron_water") then
|
||||
newnode = mcl_cauldrons.fill_levels(node, 1, "cauldron_water")
|
||||
end
|
||||
end
|
||||
if newnode then
|
||||
minetest.set_node(pos, newnode)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -132,6 +132,9 @@ return {
|
|||
"todoporlalibertad",
|
||||
"Marcin Serwin",
|
||||
}},
|
||||
{S("Funders"), 0xF7FF00, {
|
||||
"40W",
|
||||
}},
|
||||
{S("Special thanks"), 0x00E9FF, {
|
||||
"celeron55 for creating Minetest",
|
||||
"Jordach for the jukebox music compilation from Big Freaking Dig",
|
||||
|
|
|
@ -348,6 +348,23 @@ minetest.register_node("mcl_banners:hanging_banner", {
|
|||
end,
|
||||
})
|
||||
|
||||
local function wash_banner(itemstack)
|
||||
local imeta = itemstack:get_meta()
|
||||
local layers_raw = imeta:get_string("layers")
|
||||
local layers = minetest.deserialize(layers_raw)
|
||||
if type(layers) == "table" and #layers > 0 then
|
||||
table.remove(layers)
|
||||
imeta:set_string("layers", minetest.serialize(layers))
|
||||
local newdesc = mcl_banners.make_advanced_banner_description(itemstack:get_definition().description, layers)
|
||||
local mname = imeta:get_string("name")
|
||||
-- Don't change description if item has a name
|
||||
if mname == "" then
|
||||
imeta:set_string("description", newdesc)
|
||||
end
|
||||
return itemstack
|
||||
end
|
||||
end
|
||||
|
||||
-- for pattern_name, pattern in pairs(patterns) do
|
||||
for colorid, colortab in pairs(mcl_banners.colors) do
|
||||
for i, pattern_name in ipairs(pattern_names) do
|
||||
|
@ -425,6 +442,10 @@ for colorid, colortab in pairs(mcl_banners.colors) do
|
|||
groups = groups,
|
||||
stack_max = 16,
|
||||
|
||||
_mcl_on_wash = function(itemstack)
|
||||
return wash_banner(itemstack)
|
||||
end,
|
||||
|
||||
on_place = function(itemstack, placer, pointed_thing)
|
||||
local above = pointed_thing.above
|
||||
local under = pointed_thing.under
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
# `mcl_cauldrons`
|
||||
|
||||
This mod add an API to add cauldrons to mcl.
|
||||
|
||||
|
||||
Node definitions
|
||||
----------------
|
||||
|
||||
Extensions to the base node definitions (as passed to `minetest.register_node()`) for cauldrons:
|
||||
|
||||
* `.groups.cauldron`: 1 - is a cauldron
|
||||
* `.groups.cauldron_filled`: number 0..3 - content level (0=empty, 3=full)
|
||||
* `.groups.cauldron_maximum`: number 1.. - maximum contents level
|
||||
* `._mcl_cauldron_substance`: string - content of cauldron (nil for empty)
|
||||
|
||||
|
||||
### `mcl_cauldrons.registered_cauldrons`
|
||||
Table containing cauldron definitions, indexed by name.
|
||||
|
||||
### `mcl_cauldrons.register_cauldron_node(nodename, cauldron_def)`
|
||||
|
||||
|
||||
Cauldron interactions
|
||||
---------------------
|
||||
|
||||
### `mcl_cauldrons.find_cauldron(substance, fill_level)`
|
||||
Returns table, { node\_name, node\_definition }, returns nil if no match.
|
||||
Find registered cauldron best matching substance and fill level.
|
||||
* `substance`: string, one of the groups keys qualifying the content (e.g. `"cauldron_water"`); empty string for empty cauldron.
|
||||
* `fill_level`: desired fill level of cauldron; `nil` for first/any match; 0 resolves to empty cauldron.
|
||||
|
||||
### `mcl_cauldrons.is_cauldron(node)`
|
||||
Returns boolean.
|
||||
Test is nodename describes a cauldron.
|
||||
* `node`: Minetest node { name, param1, param2 }
|
||||
|
||||
### `mcl_cauldrons.is_empty(node)`
|
||||
Returns boolean.
|
||||
Test cauldron is empty.
|
||||
* `node`: Minetest node { name, param1, param2 }
|
||||
|
||||
### `mcl_cauldrons.is_full(node)`
|
||||
Returns boolean.
|
||||
Test cauldron is full.
|
||||
* `node`: Minetest node { name, param1, param2 }
|
||||
|
||||
### `mcl_cauldrons.has_substance(node, substance)`
|
||||
Returns boolean.
|
||||
Test the content is a certain substance.
|
||||
* `node`: Minetest node { name, param1, param2 }
|
||||
* `substance`: string, one of the groups key qualifying the content (e.g. `"cauldron_water"`).
|
||||
|
||||
### `mcl_cauldrons.get_maximum(node, substance)`
|
||||
Returns number.
|
||||
Get the maximum number of levels for requested substance.
|
||||
* `node`: Minetest node { name, param1, param2 }
|
||||
* `substance`: string, group-key qualifying the content (e.g. `"cauldron_water"`); `nil` for any/do-not-care.
|
||||
|
||||
### `mcl_cauldrons.get_level(node, substance)`
|
||||
Returns number.
|
||||
Get the fill level of the requested substance.
|
||||
* `node`: Minetest node { name, param1, param2 }
|
||||
* `substance`: string, group-key qualifying the content (e.g. `"cauldron_water"`); `nil` for any/do-not-care.
|
||||
|
||||
### `mcl_cauldrons.set_level(node, fill_level, substance)`
|
||||
Returns node { name, param1, param2 }.
|
||||
Set the fill level of cauldron, with optional explicit substance.
|
||||
* `node`: Minetest node { name, param1, param2 }
|
||||
* `substance`: string, group-key of cauldron content; `nil` to preserve substance.
|
||||
|
||||
### `mcl_cauldrons.fill_levels(node, change_levels, substance)`
|
||||
Returns node { name, param1, param2 }.
|
||||
Increase levels in cauldron, constrained by game rules.
|
||||
* `node`: Minetest node { name, param1, param2 }
|
||||
* `substance`: string, group-key of cauldron content; `nil` to preserve substance.
|
||||
|
||||
### `mcl_cauldrons.drain_levels(nodename, change_levels, substance)`
|
||||
Returns node { name, param1, param2 }.
|
||||
Reduce levels in cauldron, constrained by game rules.
|
||||
* `node`: Minetest node { name, param1, param2 }
|
||||
* `substance`: string, group-key of cauldron content; `nil` to preserve substance.
|
||||
|
||||
### `mcl_cauldrons.register_cauldron_node(nodename, cauldron_definition, doc_alias)`
|
||||
Register cauldron's node defintion. Affects `mcl_cauldrons.registered_cauldrons` while ultimately ending up at `minetest.register_node`.
|
||||
* `nodename`: string - name to assign to registered node.
|
||||
* `cauldron_defintion`: table - node definition (expecting mcl\_cauldrons extensions).
|
||||
* `doc_alias`: string - documentation (in-game encyclopedia) entry associated with this definition.
|
||||
|
|
@ -0,0 +1,354 @@
|
|||
--- API for Cauldrons in MineClone2.
|
||||
|
||||
-- Documentation Generator is LDoc (backwards-compatible with LuaDoc)
|
||||
-- $ ldoc -f markdown ...
|
||||
|
||||
--- Table of registered cauldron nodes, indexed by name.
|
||||
-- Filled by register_cauldron_node().
|
||||
mcl_cauldrons.registered_cauldrons = {}
|
||||
--- List of recognized substances in cauldron.
|
||||
-- Filled by register_cauldron_node()
|
||||
-- @see mcl_cauldrons.list_substances
|
||||
mcl_cauldrons.substances = {}
|
||||
|
||||
|
||||
--- Provided for documentation purposes, frequently-used table format.
|
||||
--
|
||||
-- Position in world { x, y, z }
|
||||
-- @name Position
|
||||
-- @class table
|
||||
local Position = { x=nil, y=nil, z=nil }
|
||||
|
||||
--- Provided for documentation purposes, frequently-used table format.
|
||||
--
|
||||
-- Node description { name, param1, param2 }, as used by `minetest.get_node()` and `minetest.set_node()`
|
||||
-- (not to be confused with node definition)
|
||||
-- @name Node
|
||||
-- @class table
|
||||
local Node = { name=nil, param1=nil, param2=nil }
|
||||
|
||||
-- symbolic constants.
|
||||
|
||||
--- Levels of cauldron change per bucket.
|
||||
mcl_cauldrons.BUCKET_FILL_LEVELS = 3
|
||||
--- Levels of cauldron change per bottle (potion).
|
||||
mcl_cauldrons.BOTTLE_FILL_LEVELS = 1
|
||||
|
||||
|
||||
--- Determine registered cauldron satisfying specifications.
|
||||
--
|
||||
-- Cauldrons are described by two state variables: { substance, fill\_level }.
|
||||
--
|
||||
-- Determine the cauldron node definition from these states.
|
||||
--
|
||||
-- e.g. `make_cauldron("water", 2)` -> `"mcl_cauldrons:cauldron_water_2"`
|
||||
--
|
||||
-- @param substance string : Desired cauldron substance, nil for any substance.
|
||||
-- @param fill_level number : Desired cauldron fill level, nil to match any.
|
||||
-- @return 2-value: cauldron node name (string), cauldron node definition (table)
|
||||
function mcl_cauldrons.make_cauldron(substance, fill_level)
|
||||
local empty_nodename = "mcl_cauldrons:cauldron"
|
||||
local empty_nodedef = mcl_cauldrons.registered_cauldrons[empty_nodename]
|
||||
if (substance == "") then
|
||||
return empty_nodename, empty_nodedef
|
||||
end
|
||||
for nodename, nodedef in pairs(mcl_cauldrons.registered_cauldrons) do
|
||||
-- matched on substance: 'any', or exact match from .groups.
|
||||
local match_substance = (substance == nil) or (nodedef._mcl_cauldron_substance == substance)
|
||||
-- matched on fill_level: 'any', or exact match from .groups.
|
||||
local match_level = (fill_level == nil) or (nodedef.groups.cauldron_filled == fill_level)
|
||||
if match_substance and match_level then
|
||||
return nodename, nodedef
|
||||
end
|
||||
end
|
||||
-- no match, use empty.
|
||||
return empty_nodename, empty_nodedef
|
||||
end
|
||||
|
||||
--- Test: node describes a cauldron
|
||||
--
|
||||
-- @param node Node : Cauldron node description (as from minetest.get_node())
|
||||
-- @return boolean: node is a cauldron
|
||||
function mcl_cauldrons.node_is_cauldron(node)
|
||||
if node == nil then return false end
|
||||
return (minetest.get_item_group(node.name, "cauldron") ~= 0)
|
||||
end
|
||||
|
||||
--- Test: position holds a cauldron
|
||||
--
|
||||
-- @param pos Position : World position (as passed to minetest.get_node())
|
||||
-- @return boolean: a cauldron is at position
|
||||
function mcl_cauldrons.is_cauldron(pos)
|
||||
local node = minetest.get_node(pos)
|
||||
return mcl_cauldrons.node_is_cauldron(node)
|
||||
end
|
||||
|
||||
--- Test: cauldron node contains specified substance
|
||||
--
|
||||
-- @param node Node : Cauldron node description
|
||||
-- @param substance string : substance that should be present in cauldron.
|
||||
-- @return boolean
|
||||
function mcl_cauldrons.node_has_substance(node, substance)
|
||||
--return (minetest.get_item_group(node.name, substance) ~= 0)
|
||||
local nodedef = minetest.registered_nodes[node.name]
|
||||
return (nodedef._mcl_cauldron_substance == substance)
|
||||
end
|
||||
|
||||
--- Test: cauldron at position contains specified substance
|
||||
--
|
||||
-- @param pos Position : World position
|
||||
-- @param substance string : substance that should be present in cauldron
|
||||
-- @return boolean
|
||||
function mcl_cauldrons.has_substance(pos, substance)
|
||||
local node = minetest.get_node(pos)
|
||||
return mcl_cauldrons.node_has_substance(node)
|
||||
end
|
||||
|
||||
--- List of supported substances
|
||||
--
|
||||
-- @return table: List of substances
|
||||
function mcl_cauldrons.list_substances()
|
||||
return mcl_cauldrons.substances
|
||||
end
|
||||
|
||||
--- Get substance inside cauldron node
|
||||
--
|
||||
-- @param node Node : Cauldron node description
|
||||
-- @return string : Substance inside cauldron
|
||||
-- @return `nil`: Cauldron is empty
|
||||
function mcl_cauldrons.node_get_substance(node)
|
||||
local nodedef = mcl_cauldrons.registered_cauldrons[node.name]
|
||||
return nodedef._mcl_cauldron_substance
|
||||
end
|
||||
|
||||
--- Get substance inside cauldron (by position)
|
||||
--
|
||||
-- @param pos Position : World position
|
||||
-- @return string: Substance inside cauldron
|
||||
-- @return `nil`: Cauldron is empty
|
||||
function mcl_cauldrons.get_substance(pos)
|
||||
local node = minetest.get_node(pos)
|
||||
return mcl_cauldrons.node_get_substance(node)
|
||||
end
|
||||
|
||||
--- Get maximum number of levels available for cauldron node -> number
|
||||
function mcl_cauldrons.node_get_maximum(node)
|
||||
local nodename = node.name
|
||||
return minetest.get_item_group(nodename, "cauldron_maximum")
|
||||
end
|
||||
|
||||
function mcl_cauldrons.get_maximum(pos)
|
||||
local node = minetest.get_node(pos)
|
||||
return mcl_cauldrons.node_get_maximum(node)
|
||||
end
|
||||
|
||||
--- Get current level from cauldron node
|
||||
--
|
||||
-- @param node Node : Cauldron node description
|
||||
-- @return number: Typically one of 0,1,2,3
|
||||
function mcl_cauldrons.node_get_level(node)
|
||||
return minetest.get_item_group(node.name, "cauldron_filled")
|
||||
end
|
||||
|
||||
--- Get current level of cauldron (by position)
|
||||
--
|
||||
-- @param pos Position : World position
|
||||
-- @return number: Typically one of 0,1,2,3
|
||||
-- Get current level of cauldron -> number
|
||||
function mcl_cauldrons.get_level(pos)
|
||||
local node = minetest.get_node(pos)
|
||||
return mcl_cauldrons.node_get_level(node)
|
||||
end
|
||||
|
||||
--- Test: cauldron node is empty
|
||||
--
|
||||
-- @param node Node : Cauldron node description
|
||||
-- @return boolean
|
||||
function mcl_cauldrons.node_is_empty(node)
|
||||
if not mcl_cauldrons.node_is_cauldron(node) then
|
||||
error("not a cauldron", node.name)
|
||||
end
|
||||
if minetest.get_item_group(node.name, "cauldron_filled") == 0 then
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
--- Test: cauldron is empty (by position)
|
||||
--
|
||||
-- @param pos Position : World position
|
||||
-- @return boolean
|
||||
function mcl_cauldrons.is_empty(pos)
|
||||
local node = minetest.get_node(pos)
|
||||
return mcl_cauldrons.node_is_empty(node)
|
||||
end
|
||||
|
||||
--- Test: cauldron node is full
|
||||
--
|
||||
-- @param node Node : Cauldron node description
|
||||
-- @return boolean
|
||||
function mcl_cauldrons.node_is_full(node)
|
||||
local maximum = mcl_cauldrons.get_maximum(node)
|
||||
local current = mcl_cauldrons.get_level(node)
|
||||
return (current >= maximum)
|
||||
end
|
||||
|
||||
--- Test: cauldron is full (by position)
|
||||
--
|
||||
-- @param pos Position : World position
|
||||
-- @return boolean
|
||||
function mcl_cauldrons.is_full(pos)
|
||||
local node = minetest.get_node(pos)
|
||||
return mcl_cauldrons.node_is_full(node)
|
||||
end
|
||||
|
||||
--- Convert cauldron node to satisfy content specifications.
|
||||
--
|
||||
-- Cauldron specification is subject to normalization based on substance
|
||||
-- and fill level (e.g. any substance at level 0 becomes empty cauldron).
|
||||
--
|
||||
-- @param node Node : node to have its contents changed
|
||||
-- @param substance string : intended cauldron substance
|
||||
-- @param fill_level number : intended fill level
|
||||
-- @return table: new cauldron node
|
||||
function mcl_cauldrons.node_set_content(node, substance, fill_level)
|
||||
local newname = mcl_cauldrons.make_cauldron(substance, fill_level)
|
||||
local newnode = table.copy(node)
|
||||
newnode.name = newname
|
||||
return newnode
|
||||
end
|
||||
|
||||
--- Place cauldron of specified substance and fill level at world position.
|
||||
--
|
||||
-- Cauldron specification is subject to normalization based on substance
|
||||
-- and fill level (e.g. any substance at level 0 becomes empty cauldron).
|
||||
--
|
||||
-- @param pos Position : World position.
|
||||
-- @param substance : string cauldron substance (item def _mcl_cauldron_substance)
|
||||
-- @param fill_level number : cauldron fill level (typically 0,1,2,3)
|
||||
-- @return table: new cauldron node (as passed to minetest.set_pos())
|
||||
function mcl_cauldrons.set_content(pos, substance, fill_level)
|
||||
local node = minetest.get_node(pos)
|
||||
if not mcl_cauldrons.is_cauldron(node) then return end
|
||||
local newnode = mcl_cauldrons.node_set_content(node, substance, fill_level)
|
||||
minetest.set_node(pos, newnode)
|
||||
return newnode
|
||||
end
|
||||
|
||||
|
||||
--- Wrapper to register cauldron-specific nodes.
|
||||
-- additional bookkeeping specific to mcl_cauldrons.
|
||||
-- @param nodename string : name of node
|
||||
-- @param nodedef table : node description
|
||||
-- @param doc_alias string : for documentation purposes, alias for this specified node name.
|
||||
function mcl_cauldrons.register_cauldron_node(nodename, nodedef, doc_alias)
|
||||
mcl_cauldrons.registered_cauldrons[nodename] = nodedef
|
||||
minetest.register_node(nodename, nodedef)
|
||||
if doc_alias and has_doc then
|
||||
doc.add_entry_alias("nodes", doc_alias, "nodes", nodename)
|
||||
end
|
||||
-- build list of supported substances.
|
||||
if table.indexof(mcl_cauldrons.substances, nodedef._mcl_cauldron_substance) == -1 then
|
||||
table.insert(mcl_cauldrons.substances, nodedef._mcl_cauldron_substance)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--- List of item proxy classes.
|
||||
--
|
||||
-- For item interactions (right-click), handlers for items that may interact
|
||||
-- with cauldron.
|
||||
mcl_cauldrons.item_proxies = {}
|
||||
|
||||
--- Add item proxy class.
|
||||
--
|
||||
-- ItemProxy classes expose `do_apply()` that carries out the duties of
|
||||
-- `on_rightclick()` (applying itemstack to cauldron node). This method
|
||||
-- returns 2 values, a boolean and an ItemStack.
|
||||
-- The first value is true if no further handling is required (typically
|
||||
-- interaction is complete), false if it could not handle the interaction.
|
||||
-- Priority of proxy classes are determined by lateness in `add_item_proxy` --
|
||||
-- later additions take priority over earlier ones, allowing for stacked mods
|
||||
-- to override basal behavior.
|
||||
--
|
||||
-- @param proxy ItemProxy : ItemProxy prototype (to have do_apply() invoked on it)
|
||||
function mcl_cauldrons.add_item_proxy(proxy)
|
||||
if table.indexof(mcl_cauldrons.item_proxies, proxy) == -1 then
|
||||
-- insert at front so newer proxies override older ones.
|
||||
table.insert(mcl_cauldrons.item_proxies, 1, proxy)
|
||||
end
|
||||
end
|
||||
|
||||
--- Invoke applying item to cauldron node.
|
||||
--
|
||||
-- carry out all the duties of on_rightclick().
|
||||
-- @return ItemStack: item to be wielded in hand (may be same `itemstack`).
|
||||
function mcl_cauldrons.apply_item(pos, node, user, itemstack)
|
||||
for _, item_handler in ipairs(mcl_cauldrons.item_proxies) do
|
||||
local handled, retval = item_handler:do_apply(pos, node, user, itemstack)
|
||||
if handled then return retval end
|
||||
end
|
||||
return itemstack
|
||||
end
|
||||
|
||||
function mcl_cauldrons.node_fill_levels(node, change_levels, substance)
|
||||
-- base rules for filling cauldrons.
|
||||
if change_levels <= 0 then
|
||||
-- no change.
|
||||
return nil
|
||||
end
|
||||
local old_level = mcl_cauldrons.node_get_level(node)
|
||||
local whole, fraction = math.modf(change_levels)
|
||||
local new_level
|
||||
if fraction > 0 then
|
||||
if math.random() < fraction then
|
||||
whole = whole + 1
|
||||
end
|
||||
end
|
||||
if (substance and mcl_cauldrons.node_has_substance(node, substance)) or (substance == nil) then
|
||||
-- same substance, add more.
|
||||
new_level = old_level + whole
|
||||
else
|
||||
-- different substance, delete old content.
|
||||
new_level = whole
|
||||
end
|
||||
-- clamp 0 through 3 inclusive.
|
||||
new_level = math.max(0, math.min(new_level, 3))
|
||||
if substance == nil then
|
||||
substance = mcl_cauldrons.node_get_substance(node)
|
||||
end
|
||||
return mcl_cauldrons.node_set_content(node, substance, new_level)
|
||||
end
|
||||
|
||||
function mcl_cauldrons.node_drain_levels(node, change_levels, substance)
|
||||
-- base rules for draining cauldrons.
|
||||
if change_levels <= 0 then
|
||||
-- no change.
|
||||
return nil
|
||||
end
|
||||
if (substance and not mcl_cauldrons.node_has_substance(node, substance)) then
|
||||
-- different substance, cannot drain.
|
||||
return nil
|
||||
end
|
||||
local old_level = mcl_cauldrons.node_get_level(node)
|
||||
local whole, fraction = math.modf(change_levels)
|
||||
local new_level
|
||||
if fraction > 0 then
|
||||
if math.random() < fraction then
|
||||
whole = whole + 1
|
||||
end
|
||||
end
|
||||
if (whole > old_level) then
|
||||
-- insufficient amount, no change.
|
||||
return nil
|
||||
end
|
||||
-- same substance, drain.
|
||||
new_level = old_level - whole
|
||||
-- clamp 0 through 3 inclusive.
|
||||
new_level = math.max(0, math.min(new_level, 3))
|
||||
if substance == nil then
|
||||
substance = mcl_cauldrons.node_get_substance(node)
|
||||
end
|
||||
return mcl_cauldrons.node_set_content(node, substance, new_level)
|
||||
end
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
|
||||
-- lava cauldron as extension of empty cauldron.
|
||||
mcl_cauldrons.register_cauldron_node("mcl_cauldrons:cauldron_lava_1",
|
||||
merge_tables(mcl_cauldrons.registered_cauldrons["mcl_cauldrons:cauldron"], {
|
||||
description = S("Cauldron (1/3 Lava)"),
|
||||
groups = {
|
||||
pickaxey = 1,
|
||||
cauldron = 1,
|
||||
cauldron_filled = 1,
|
||||
cauldron_maximum = 3,
|
||||
},
|
||||
node_box = mcl_cauldrons.cauldron_nodeboxes[1],
|
||||
collision_box = mcl_cauldrons.cauldron_nodeboxes[0],
|
||||
tiles = {
|
||||
[1]="(default_lava_source_animated.png^[verticalframe:16:0)^mcl_cauldrons_cauldron_top.png",
|
||||
},
|
||||
drop = "mcl_cauldrons:cauldron",
|
||||
_mcl_cauldron_substance = "lava",
|
||||
}), "mcl_cauldrons:cauldron")
|
||||
|
||||
-- lava cauldron 2/3 as extension of 1/3.
|
||||
mcl_cauldrons.register_cauldron_node("mcl_cauldrons:cauldron_lava_2",
|
||||
merge_tables(mcl_cauldrons.registered_cauldrons["mcl_cauldrons:cauldron_lava_1"], {
|
||||
description = S("Cauldron (2/3 Lava)"),
|
||||
groups = {
|
||||
cauldron_filled = 2,
|
||||
},
|
||||
node_box = mcl_cauldrons.cauldron_nodeboxes[2],
|
||||
}), "mcl_cauldrons:cauldron")
|
||||
|
||||
-- lava cauldron 3/3 as extension of 1/3.
|
||||
local LIGHT_LAVA = minetest.registered_nodes["mcl_core:lava_source"].light_source
|
||||
mcl_cauldrons.register_cauldron_node("mcl_cauldrons:cauldron_lava_3",
|
||||
merge_tables(mcl_cauldrons.registered_cauldrons["mcl_cauldrons:cauldron_lava_1"], {
|
||||
description = S("Cauldron (3/3 Lava)"),
|
||||
groups = {
|
||||
cauldron_filled = 3,
|
||||
},
|
||||
paramtype = "light",
|
||||
light_source = LIGHT_LAVA,
|
||||
node_box = mcl_cauldrons.cauldron_nodeboxes[3],
|
||||
}), "mcl_cauldrons:cauldron")
|
||||
|
||||
|
||||
|
||||
-- Bucket interaction, lava.
|
||||
|
||||
local BucketProxy = mcl_cauldrons.BucketProxy
|
||||
|
||||
function BucketProxy.is_lava(itemstack)
|
||||
if itemstack:get_name() == "mcl_buckets:bucket_lava" then return true end
|
||||
-- other tests.
|
||||
end
|
||||
|
||||
function BucketProxy:sound_lava(new_itemstack, new_cauldron_node)
|
||||
local nodedef = minetest.registered_nodes["mcl_core:lava_source"]
|
||||
if self.is_empty(new_itemstack) then
|
||||
-- lava placed.
|
||||
return nodedef.sounds.place, { pitch = 1.0 + math.random(-10, 10) * .005 }
|
||||
else
|
||||
-- lava taken.
|
||||
return nodedef.sounds.dug, { pitch = 1.0 + math.random(-10, 10) * .005 }
|
||||
end
|
||||
end
|
||||
|
||||
function BucketProxy.make_lava(old_itemstack, cauldron_node)
|
||||
return ItemStack("mcl_buckets:bucket_lava")
|
||||
end
|
||||
|
||||
|
||||
BucketProxy:add_bucket_rules("lava", BucketProxy.is_lava, BucketProxy.make_lava, BucketProxy.sound_lava)
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
|
||||
-- river water cauldron as extension of empty cauldron.
|
||||
mcl_cauldrons.register_cauldron_node("mcl_cauldrons:cauldron_river_water_1",
|
||||
merge_tables(mcl_cauldrons.registered_cauldrons["mcl_cauldrons:cauldron"], {
|
||||
description = S("Cauldron (1/3 River Water)"),
|
||||
groups = {
|
||||
pickaxey = 1,
|
||||
cauldron = 1,
|
||||
cauldron_filled = 1,
|
||||
cauldron_maximum = 3,
|
||||
},
|
||||
node_box = mcl_cauldrons.cauldron_nodeboxes[1],
|
||||
collision_box = mcl_cauldrons.cauldron_nodeboxes[0],
|
||||
tiles = {
|
||||
[1]="(default_river_water_source_animated.png^[verticalframe:16:0)^mcl_cauldrons_cauldron_top.png",
|
||||
},
|
||||
drop = "mcl_cauldrons:cauldron",
|
||||
_mcl_cauldron_substance = "river_water",
|
||||
}), "mcl_cauldrons:cauldron")
|
||||
-- water cauldron 2/3 as extension of 1/3.
|
||||
mcl_cauldrons.register_cauldron_node("mcl_cauldrons:cauldron_river_water_2",
|
||||
merge_tables(mcl_cauldrons.registered_cauldrons["mcl_cauldrons:cauldron_river_water_1"], {
|
||||
description = S("Cauldron (2/3 River Water)"),
|
||||
groups = {
|
||||
cauldron_filled = 2,
|
||||
},
|
||||
node_box = mcl_cauldrons.cauldron_nodeboxes[2],
|
||||
}), "mcl_cauldrons:cauldron")
|
||||
-- water cauldron 3/3 as extension of 1/3.
|
||||
mcl_cauldrons.register_cauldron_node("mcl_cauldrons:cauldron_river_water_3",
|
||||
merge_tables(mcl_cauldrons.registered_cauldrons["mcl_cauldrons:cauldron_river_water_1"], {
|
||||
description = S("Cauldron (3/3 River Water)"),
|
||||
groups = {
|
||||
cauldron_filled = 3,
|
||||
},
|
||||
node_box = mcl_cauldrons.cauldron_nodeboxes[3],
|
||||
}), "mcl_cauldrons:cauldron")
|
||||
|
||||
|
||||
-- bucket interactions, river water.
|
||||
|
||||
local BucketProxy = mcl_cauldrons.BucketProxy
|
||||
|
||||
function BucketProxy.is_river_water(itemstack)
|
||||
if (itemstack:get_name() == "mcl_buckets:bucket_river_water") then return true end
|
||||
-- other tests.
|
||||
end
|
||||
|
||||
function BucketProxy.make_river_water(itemstack, cauldron_node)
|
||||
for scan_name, scan_def in pairs(minetest.registered_items) do
|
||||
-- TODO: expand mcl_buckets node definitions.
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
BucketProxy:add_bucket_rules("river_water", BucketProxy.is_river_water, "mcl_buckets:bucket_river_water", BucketProxy.sound_water)
|
||||
|
||||
|
||||
|
||||
-- bottle interactions, river water.
|
||||
|
||||
local BottleProxy = mcl_cauldrons.BottleProxy
|
||||
|
||||
function BottleProxy.is_river_water(itemstack)
|
||||
if (itemstack:get_name() == "mcl_potions:river_water") then return true end
|
||||
-- other tests.
|
||||
end
|
||||
|
||||
function BottleProxy.make_river_water(old_itemstack, cauldron_node)
|
||||
return ItemStack("mcl_potions:river_water")
|
||||
end
|
||||
|
||||
|
||||
BottleProxy:add_bottle_rules("river_water", BottleProxy.is_river_water, "mcl_potions:bottle_river_water", BottleProxy.sound_water)
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
-- LDoc (LuaDoc derivative) configuration; not a linker script.
|
||||
-- $ luarocks install --local ldoc markdown
|
||||
|
||||
project = 'mcl_cauldrons'
|
||||
file = { 'api.lua', 'cauldron_lava.lua', 'cauldron_river_water.lua', 'init.lua', 'register.lua' }
|
||||
all = true
|
||||
format = 'markdown'
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||
<head>
|
||||
<title>Reference</title>
|
||||
<link rel="stylesheet" href="ldoc.css" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="container">
|
||||
|
||||
<div id="product">
|
||||
<div id="product_logo"></div>
|
||||
<div id="product_name"><big><b></b></big></div>
|
||||
<div id="product_description"></div>
|
||||
</div> <!-- id="product" -->
|
||||
|
||||
|
||||
<div id="main">
|
||||
|
||||
|
||||
<!-- Menu -->
|
||||
|
||||
<div id="navigation">
|
||||
<br/>
|
||||
<h1>mcl_cauldrons</h1>
|
||||
|
||||
|
||||
|
||||
|
||||
<h2>Modules</h2>
|
||||
<ul class="nowrap">
|
||||
<li><a href="modules/api.html">api</a></li>
|
||||
<li><a href="modules/init.html">init</a></li>
|
||||
<li><a href="modules/register.html">register</a></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="content">
|
||||
|
||||
|
||||
|
||||
<h2>Modules</h2>
|
||||
<table class="module_list">
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="modules/api.html">api</a></td>
|
||||
<td class="summary">API for Cauldrons in MineClone2.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="modules/init.html">init</a></td>
|
||||
<td class="summary">Initialization (primary entry point) for mcl_cauldrons.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="modules/register.html">register</a></td>
|
||||
<td class="summary">Base cauldron types.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</div> <!-- id="content" -->
|
||||
</div> <!-- id="main" -->
|
||||
<div id="about">
|
||||
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
|
||||
<i style="float:right;">Last updated 2021-11-12 11:20:21 </i>
|
||||
</div> <!-- id="about" -->
|
||||
</div> <!-- id="container" -->
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,303 @@
|
|||
/* BEGIN RESET
|
||||
|
||||
Copyright (c) 2010, Yahoo! Inc. All rights reserved.
|
||||
Code licensed under the BSD License:
|
||||
http://developer.yahoo.com/yui/license.html
|
||||
version: 2.8.2r1
|
||||
*/
|
||||
html {
|
||||
color: #000;
|
||||
background: #FFF;
|
||||
}
|
||||
body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,button,textarea,p,blockquote,th,td {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
}
|
||||
fieldset,img {
|
||||
border: 0;
|
||||
}
|
||||
address,caption,cite,code,dfn,em,strong,th,var,optgroup {
|
||||
font-style: inherit;
|
||||
font-weight: inherit;
|
||||
}
|
||||
del,ins {
|
||||
text-decoration: none;
|
||||
}
|
||||
li {
|
||||
margin-left: 20px;
|
||||
}
|
||||
caption,th {
|
||||
text-align: left;
|
||||
}
|
||||
h1,h2,h3,h4,h5,h6 {
|
||||
font-size: 100%;
|
||||
font-weight: bold;
|
||||
}
|
||||
q:before,q:after {
|
||||
content: '';
|
||||
}
|
||||
abbr,acronym {
|
||||
border: 0;
|
||||
font-variant: normal;
|
||||
}
|
||||
sup {
|
||||
vertical-align: baseline;
|
||||
}
|
||||
sub {
|
||||
vertical-align: baseline;
|
||||
}
|
||||
legend {
|
||||
color: #000;
|
||||
}
|
||||
input,button,textarea,select,optgroup,option {
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
font-style: inherit;
|
||||
font-weight: inherit;
|
||||
}
|
||||
input,button,textarea,select {*font-size:100%;
|
||||
}
|
||||
/* END RESET */
|
||||
|
||||
body {
|
||||
margin-left: 1em;
|
||||
margin-right: 1em;
|
||||
font-family: arial, helvetica, geneva, sans-serif;
|
||||
background-color: #ffffff; margin: 0px;
|
||||
}
|
||||
|
||||
code, tt { font-family: monospace; font-size: 1.1em; }
|
||||
span.parameter { font-family:monospace; }
|
||||
span.parameter:after { content:":"; }
|
||||
span.types:before { content:"("; }
|
||||
span.types:after { content:")"; }
|
||||
.type { font-weight: bold; font-style:italic }
|
||||
|
||||
body, p, td, th { font-size: .95em; line-height: 1.2em;}
|
||||
|
||||
p, ul { margin: 10px 0 0 0px;}
|
||||
|
||||
strong { font-weight: bold;}
|
||||
|
||||
em { font-style: italic;}
|
||||
|
||||
h1 {
|
||||
font-size: 1.5em;
|
||||
margin: 20px 0 20px 0;
|
||||
}
|
||||
h2, h3, h4 { margin: 15px 0 10px 0; }
|
||||
h2 { font-size: 1.25em; }
|
||||
h3 { font-size: 1.15em; }
|
||||
h4 { font-size: 1.06em; }
|
||||
|
||||
a:link { font-weight: bold; color: #004080; text-decoration: none; }
|
||||
a:visited { font-weight: bold; color: #006699; text-decoration: none; }
|
||||
a:link:hover { text-decoration: underline; }
|
||||
|
||||
hr {
|
||||
color:#cccccc;
|
||||
background: #00007f;
|
||||
height: 1px;
|
||||
}
|
||||
|
||||
blockquote { margin-left: 3em; }
|
||||
|
||||
ul { list-style-type: disc; }
|
||||
|
||||
p.name {
|
||||
font-family: "Andale Mono", monospace;
|
||||
padding-top: 1em;
|
||||
}
|
||||
|
||||
pre {
|
||||
background-color: rgb(245, 245, 245);
|
||||
border: 1px solid #C0C0C0; /* silver */
|
||||
padding: 10px;
|
||||
margin: 10px 0 10px 0;
|
||||
overflow: auto;
|
||||
font-family: "Andale Mono", monospace;
|
||||
}
|
||||
|
||||
pre.example {
|
||||
font-size: .85em;
|
||||
}
|
||||
|
||||
table.index { border: 1px #00007f; }
|
||||
table.index td { text-align: left; vertical-align: top; }
|
||||
|
||||
#container {
|
||||
margin-left: 1em;
|
||||
margin-right: 1em;
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
#product {
|
||||
text-align: center;
|
||||
border-bottom: 1px solid #cccccc;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
#product big {
|
||||
font-size: 2em;
|
||||
}
|
||||
|
||||
#main {
|
||||
background-color: #f0f0f0;
|
||||
border-left: 2px solid #cccccc;
|
||||
}
|
||||
|
||||
#navigation {
|
||||
float: left;
|
||||
width: 14em;
|
||||
vertical-align: top;
|
||||
background-color: #f0f0f0;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
#navigation h2 {
|
||||
background-color:#e7e7e7;
|
||||
font-size:1.1em;
|
||||
color:#000000;
|
||||
text-align: left;
|
||||
padding:0.2em;
|
||||
border-top:1px solid #dddddd;
|
||||
border-bottom:1px solid #dddddd;
|
||||
}
|
||||
|
||||
#navigation ul
|
||||
{
|
||||
font-size:1em;
|
||||
list-style-type: none;
|
||||
margin: 1px 1px 10px 1px;
|
||||
}
|
||||
|
||||
#navigation li {
|
||||
text-indent: -1em;
|
||||
display: block;
|
||||
margin: 3px 0px 0px 22px;
|
||||
}
|
||||
|
||||
#navigation li li a {
|
||||
margin: 0px 3px 0px -1em;
|
||||
}
|
||||
|
||||
#content {
|
||||
margin-left: 14em;
|
||||
padding: 1em;
|
||||
width: 700px;
|
||||
border-left: 2px solid #cccccc;
|
||||
border-right: 2px solid #cccccc;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
#about {
|
||||
clear: both;
|
||||
padding: 5px;
|
||||
border-top: 2px solid #cccccc;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
@media print {
|
||||
body {
|
||||
font: 12pt "Times New Roman", "TimeNR", Times, serif;
|
||||
}
|
||||
a { font-weight: bold; color: #004080; text-decoration: underline; }
|
||||
|
||||
#main {
|
||||
background-color: #ffffff;
|
||||
border-left: 0px;
|
||||
}
|
||||
|
||||
#container {
|
||||
margin-left: 2%;
|
||||
margin-right: 2%;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
#content {
|
||||
padding: 1em;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
#navigation {
|
||||
display: none;
|
||||
}
|
||||
pre.example {
|
||||
font-family: "Andale Mono", monospace;
|
||||
font-size: 10pt;
|
||||
page-break-inside: avoid;
|
||||
}
|
||||
}
|
||||
|
||||
table.module_list {
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
border-color: #cccccc;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
table.module_list td {
|
||||
border-width: 1px;
|
||||
padding: 3px;
|
||||
border-style: solid;
|
||||
border-color: #cccccc;
|
||||
}
|
||||
table.module_list td.name { background-color: #f0f0f0; min-width: 200px; }
|
||||
table.module_list td.summary { width: 100%; }
|
||||
|
||||
|
||||
table.function_list {
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
border-color: #cccccc;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
table.function_list td {
|
||||
border-width: 1px;
|
||||
padding: 3px;
|
||||
border-style: solid;
|
||||
border-color: #cccccc;
|
||||
}
|
||||
table.function_list td.name { background-color: #f0f0f0; min-width: 200px; }
|
||||
table.function_list td.summary { width: 100%; }
|
||||
|
||||
ul.nowrap {
|
||||
overflow:auto;
|
||||
white-space:nowrap;
|
||||
}
|
||||
|
||||
dl.table dt, dl.function dt {border-top: 1px solid #ccc; padding-top: 1em;}
|
||||
dl.table dd, dl.function dd {padding-bottom: 1em; margin: 10px 0 0 20px;}
|
||||
dl.table h3, dl.function h3 {font-size: .95em;}
|
||||
|
||||
/* stop sublists from having initial vertical space */
|
||||
ul ul { margin-top: 0px; }
|
||||
ol ul { margin-top: 0px; }
|
||||
ol ol { margin-top: 0px; }
|
||||
ul ol { margin-top: 0px; }
|
||||
|
||||
/* make the target distinct; helps when we're navigating to a function */
|
||||
a:target + * {
|
||||
background-color: #FF9;
|
||||
}
|
||||
|
||||
|
||||
/* styles for prettification of source */
|
||||
pre .comment { color: #558817; }
|
||||
pre .constant { color: #a8660d; }
|
||||
pre .escape { color: #844631; }
|
||||
pre .keyword { color: #aa5050; font-weight: bold; }
|
||||
pre .library { color: #0e7c6b; }
|
||||
pre .marker { color: #512b1e; background: #fedc56; font-weight: bold; }
|
||||
pre .string { color: #8080ff; }
|
||||
pre .number { color: #f8660d; }
|
||||
pre .operator { color: #2239a8; font-weight: bold; }
|
||||
pre .preprocessor, pre .prepro { color: #a33243; }
|
||||
pre .global { color: #800080; }
|
||||
pre .user-keyword { color: #800080; }
|
||||
pre .prompt { color: #558817; }
|
||||
pre .url { color: #272fc2; text-decoration: underline; }
|
||||
|
|
@ -0,0 +1,905 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||
<head>
|
||||
<title>Reference</title>
|
||||
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="container">
|
||||
|
||||
<div id="product">
|
||||
<div id="product_logo"></div>
|
||||
<div id="product_name"><big><b></b></big></div>
|
||||
<div id="product_description"></div>
|
||||
</div> <!-- id="product" -->
|
||||
|
||||
|
||||
<div id="main">
|
||||
|
||||
|
||||
<!-- Menu -->
|
||||
|
||||
<div id="navigation">
|
||||
<br/>
|
||||
<h1>mcl_cauldrons</h1>
|
||||
|
||||
<ul>
|
||||
<li><a href="../index.html">Index</a></li>
|
||||
</ul>
|
||||
|
||||
<h2>Contents</h2>
|
||||
<ul>
|
||||
<li><a href="#Functions">Functions</a></li>
|
||||
<li><a href="#Tables">Tables</a></li>
|
||||
<li><a href="#Fields">Fields</a></li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h2>Modules</h2>
|
||||
<ul class="nowrap">
|
||||
<li><strong>api</strong></li>
|
||||
<li><a href="../modules/init.html">init</a></li>
|
||||
<li><a href="../modules/register.html">register</a></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="content">
|
||||
|
||||
<h1>Module <code>api</code></h1>
|
||||
<p>API for Cauldrons in MineClone2.</p>
|
||||
<p>
|
||||
|
||||
</p>
|
||||
|
||||
|
||||
<h2><a href="#Functions">Functions</a></h2>
|
||||
<table class="function_list">
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#mcl_cauldrons.make_cauldron">mcl_cauldrons.make_cauldron (substance, fill_level)</a></td>
|
||||
<td class="summary">Determine registered cauldron satisfying specifications.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#mcl_cauldrons.node_is_cauldron">mcl_cauldrons.node_is_cauldron (node)</a></td>
|
||||
<td class="summary">Test: node describes a cauldron</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#mcl_cauldrons.is_cauldron">mcl_cauldrons.is_cauldron (pos)</a></td>
|
||||
<td class="summary">Test: position holds a cauldron</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#mcl_cauldrons.node_has_substance">mcl_cauldrons.node_has_substance (node, substance)</a></td>
|
||||
<td class="summary">Test: cauldron node contains specified substance</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#mcl_cauldrons.has_substance">mcl_cauldrons.has_substance (pos, substance)</a></td>
|
||||
<td class="summary">Test: cauldron at position contains specified substance</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#mcl_cauldrons.list_substances">mcl_cauldrons.list_substances ()</a></td>
|
||||
<td class="summary">List of supported substances</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#mcl_cauldrons.node_get_substance">mcl_cauldrons.node_get_substance (node)</a></td>
|
||||
<td class="summary">Get substance inside cauldron node</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#mcl_cauldrons.get_substance">mcl_cauldrons.get_substance (pos)</a></td>
|
||||
<td class="summary">Get substance inside cauldron (by position)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#mcl_cauldrons.node_get_maximum">mcl_cauldrons.node_get_maximum (node)</a></td>
|
||||
<td class="summary">Get maximum number of levels available for cauldron node -> number</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#mcl_cauldrons.node_get_level">mcl_cauldrons.node_get_level (node)</a></td>
|
||||
<td class="summary">Get current level from cauldron node</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#mcl_cauldrons.get_level">mcl_cauldrons.get_level (pos)</a></td>
|
||||
<td class="summary">Get current level of cauldron (by position)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#mcl_cauldrons.node_is_empty">mcl_cauldrons.node_is_empty (node)</a></td>
|
||||
<td class="summary">Test: cauldron node is empty</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#mcl_cauldrons.is_empty">mcl_cauldrons.is_empty (pos)</a></td>
|
||||
<td class="summary">Test: cauldron is empty (by position)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#mcl_cauldrons.node_is_full">mcl_cauldrons.node_is_full (node)</a></td>
|
||||
<td class="summary">Test: cauldron node is full</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#mcl_cauldrons.is_full">mcl_cauldrons.is_full (pos)</a></td>
|
||||
<td class="summary">Test: cauldron is full (by position)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#mcl_cauldrons.node_set_content">mcl_cauldrons.node_set_content (node, substance, fill_level)</a></td>
|
||||
<td class="summary">Convert cauldron node to satisfy content specifications.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#mcl_cauldrons.set_content">mcl_cauldrons.set_content (pos, substance, fill_level)</a></td>
|
||||
<td class="summary">Place cauldron of specified substance and fill level at world position.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#mcl_cauldrons.register_cauldron_node">mcl_cauldrons.register_cauldron_node (nodename, nodedef, doc_alias)</a></td>
|
||||
<td class="summary">Wrapper to register cauldron-specific nodes.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#mcl_cauldrons.add_item_proxy">mcl_cauldrons.add_item_proxy (proxy)</a></td>
|
||||
<td class="summary">Add item proxy class.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#mcl_cauldrons.apply_item">mcl_cauldrons.apply_item (pos, node, user, itemstack)</a></td>
|
||||
<td class="summary">Invoke applying item to cauldron node.</td>
|
||||
</tr>
|
||||
</table>
|
||||
<h2><a href="#Tables">Tables</a></h2>
|
||||
<table class="function_list">
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#mcl_cauldrons.registered_cauldrons">mcl_cauldrons.registered_cauldrons</a></td>
|
||||
<td class="summary">Table of registered cauldron nodes, indexed by name.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#mcl_cauldrons.substances">mcl_cauldrons.substances</a></td>
|
||||
<td class="summary">List of recognized substances in cauldron.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#Position">Position</a></td>
|
||||
<td class="summary">Provided for documentation purposes, frequently-used table format.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#Node">Node</a></td>
|
||||
<td class="summary">Provided for documentation purposes, frequently-used table format.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#mcl_cauldrons.item_proxies">mcl_cauldrons.item_proxies</a></td>
|
||||
<td class="summary">List of item proxy classes.</td>
|
||||
</tr>
|
||||
</table>
|
||||
<h2><a href="#Fields">Fields</a></h2>
|
||||
<table class="function_list">
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#mcl_cauldrons.BUCKET_FILL_LEVELS">mcl_cauldrons.BUCKET_FILL_LEVELS</a></td>
|
||||
<td class="summary">Levels of cauldron change per bucket.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#mcl_cauldrons.BOTTLE_FILL_LEVELS">mcl_cauldrons.BOTTLE_FILL_LEVELS</a></td>
|
||||
<td class="summary">Levels of cauldron change per bottle (potion).</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<br/>
|
||||
<br/>
|
||||
|
||||
|
||||
<h2 class="section-header "><a name="Functions"></a>Functions</h2>
|
||||
|
||||
<dl class="function">
|
||||
<dt>
|
||||
<a name = "mcl_cauldrons.make_cauldron"></a>
|
||||
<strong>mcl_cauldrons.make_cauldron (substance, fill_level)</strong>
|
||||
</dt>
|
||||
<dd>
|
||||
Determine registered cauldron satisfying specifications. </p>
|
||||
|
||||
<p> Cauldrons are described by two state variables: { substance, fill_level }.</p>
|
||||
|
||||
<p> Determine the cauldron node definition from these states.</p>
|
||||
|
||||
<p> e.g. <code>make_cauldron("water", 2)</code> -> <code>"mcl_cauldrons:cauldron_water_2"</code>
|
||||
|
||||
|
||||
<h3>Parameters:</h3>
|
||||
<ul>
|
||||
<li><span class="parameter">substance</span>
|
||||
string : Desired cauldron substance, nil for any substance.
|
||||
</li>
|
||||
<li><span class="parameter">fill_level</span>
|
||||
number : Desired cauldron fill level, nil to match any.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3>Returns:</h3>
|
||||
<ol>
|
||||
|
||||
2-value: cauldron node name (string), cauldron node definition (table)
|
||||
</ol>
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
<dt>
|
||||
<a name = "mcl_cauldrons.node_is_cauldron"></a>
|
||||
<strong>mcl_cauldrons.node_is_cauldron (node)</strong>
|
||||
</dt>
|
||||
<dd>
|
||||
Test: node describes a cauldron
|
||||
|
||||
|
||||
<h3>Parameters:</h3>
|
||||
<ul>
|
||||
<li><span class="parameter">node</span>
|
||||
Node : Cauldron node description (as from minetest.get_node())
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3>Returns:</h3>
|
||||
<ol>
|
||||
|
||||
boolean: node is a cauldron
|
||||
</ol>
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
<dt>
|
||||
<a name = "mcl_cauldrons.is_cauldron"></a>
|
||||
<strong>mcl_cauldrons.is_cauldron (pos)</strong>
|
||||
</dt>
|
||||
<dd>
|
||||
Test: position holds a cauldron
|
||||
|
||||
|
||||
<h3>Parameters:</h3>
|
||||
<ul>
|
||||
<li><span class="parameter">pos</span>
|
||||
Position : World position (as passed to minetest.get_node())
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3>Returns:</h3>
|
||||
<ol>
|
||||
|
||||
boolean: a cauldron is at position
|
||||
</ol>
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
<dt>
|
||||
<a name = "mcl_cauldrons.node_has_substance"></a>
|
||||
<strong>mcl_cauldrons.node_has_substance (node, substance)</strong>
|
||||
</dt>
|
||||
<dd>
|
||||
Test: cauldron node contains specified substance
|
||||
|
||||
|
||||
<h3>Parameters:</h3>
|
||||
<ul>
|
||||
<li><span class="parameter">node</span>
|
||||
Node : Cauldron node description
|
||||
</li>
|
||||
<li><span class="parameter">substance</span>
|
||||
string : substance that should be present in cauldron.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3>Returns:</h3>
|
||||
<ol>
|
||||
|
||||
boolean
|
||||
</ol>
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
<dt>
|
||||
<a name = "mcl_cauldrons.has_substance"></a>
|
||||
<strong>mcl_cauldrons.has_substance (pos, substance)</strong>
|
||||
</dt>
|
||||
<dd>
|
||||
Test: cauldron at position contains specified substance
|
||||
|
||||
|
||||
<h3>Parameters:</h3>
|
||||
<ul>
|
||||
<li><span class="parameter">pos</span>
|
||||
Position : World position
|
||||
</li>
|
||||
<li><span class="parameter">substance</span>
|
||||
string : substance that should be present in cauldron
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3>Returns:</h3>
|
||||
<ol>
|
||||
|
||||
boolean
|
||||
</ol>
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
<dt>
|
||||
<a name = "mcl_cauldrons.list_substances"></a>
|
||||
<strong>mcl_cauldrons.list_substances ()</strong>
|
||||
</dt>
|
||||
<dd>
|
||||
List of supported substances
|
||||
|
||||
|
||||
|
||||
<h3>Returns:</h3>
|
||||
<ol>
|
||||
|
||||
table: List of substances
|
||||
</ol>
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
<dt>
|
||||
<a name = "mcl_cauldrons.node_get_substance"></a>
|
||||
<strong>mcl_cauldrons.node_get_substance (node)</strong>
|
||||
</dt>
|
||||
<dd>
|
||||
Get substance inside cauldron node
|
||||
|
||||
|
||||
<h3>Parameters:</h3>
|
||||
<ul>
|
||||
<li><span class="parameter">node</span>
|
||||
Node : Cauldron node description
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3>Returns:</h3>
|
||||
<ol>
|
||||
<li>
|
||||
string : Substance inside cauldron</li>
|
||||
<li>
|
||||
<code>nil</code>: Cauldron is empty</li>
|
||||
</ol>
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
<dt>
|
||||
<a name = "mcl_cauldrons.get_substance"></a>
|
||||
<strong>mcl_cauldrons.get_substance (pos)</strong>
|
||||
</dt>
|
||||
<dd>
|
||||
Get substance inside cauldron (by position)
|
||||
|
||||
|
||||
<h3>Parameters:</h3>
|
||||
<ul>
|
||||
<li><span class="parameter">pos</span>
|
||||
Position : World position
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3>Returns:</h3>
|
||||
<ol>
|
||||
<li>
|
||||
string: Substance inside cauldron</li>
|
||||
<li>
|
||||
<code>nil</code>: Cauldron is empty</li>
|
||||
</ol>
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
<dt>
|
||||
<a name = "mcl_cauldrons.node_get_maximum"></a>
|
||||
<strong>mcl_cauldrons.node_get_maximum (node)</strong>
|
||||
</dt>
|
||||
<dd>
|
||||
Get maximum number of levels available for cauldron node -> number
|
||||
|
||||
|
||||
<h3>Parameters:</h3>
|
||||
<ul>
|
||||
<li><span class="parameter">node</span>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
<dt>
|
||||
<a name = "mcl_cauldrons.node_get_level"></a>
|
||||
<strong>mcl_cauldrons.node_get_level (node)</strong>
|
||||
</dt>
|
||||
<dd>
|
||||
Get current level from cauldron node
|
||||
|
||||
|
||||
<h3>Parameters:</h3>
|
||||
<ul>
|
||||
<li><span class="parameter">node</span>
|
||||
Node : Cauldron node description
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3>Returns:</h3>
|
||||
<ol>
|
||||
|
||||
number: Typically one of 0,1,2,3
|
||||
</ol>
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
<dt>
|
||||
<a name = "mcl_cauldrons.get_level"></a>
|
||||
<strong>mcl_cauldrons.get_level (pos)</strong>
|
||||
</dt>
|
||||
<dd>
|
||||
Get current level of cauldron (by position)
|
||||
|
||||
|
||||
<h3>Parameters:</h3>
|
||||
<ul>
|
||||
<li><span class="parameter">pos</span>
|
||||
Position : World position
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3>Returns:</h3>
|
||||
<ol>
|
||||
|
||||
number: Typically one of 0,1,2,3
|
||||
Get current level of cauldron -> number
|
||||
</ol>
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
<dt>
|
||||
<a name = "mcl_cauldrons.node_is_empty"></a>
|
||||
<strong>mcl_cauldrons.node_is_empty (node)</strong>
|
||||
</dt>
|
||||
<dd>
|
||||
Test: cauldron node is empty
|
||||
|
||||
|
||||
<h3>Parameters:</h3>
|
||||
<ul>
|
||||
<li><span class="parameter">node</span>
|
||||
Node : Cauldron node description
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3>Returns:</h3>
|
||||
<ol>
|
||||
|
||||
boolean
|
||||
</ol>
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
<dt>
|
||||
<a name = "mcl_cauldrons.is_empty"></a>
|
||||
<strong>mcl_cauldrons.is_empty (pos)</strong>
|
||||
</dt>
|
||||
<dd>
|
||||
Test: cauldron is empty (by position)
|
||||
|
||||
|
||||
<h3>Parameters:</h3>
|
||||
<ul>
|
||||
<li><span class="parameter">pos</span>
|
||||
Position : World position
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3>Returns:</h3>
|
||||
<ol>
|
||||
|
||||
boolean
|
||||
</ol>
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
<dt>
|
||||
<a name = "mcl_cauldrons.node_is_full"></a>
|
||||
<strong>mcl_cauldrons.node_is_full (node)</strong>
|
||||
</dt>
|
||||
<dd>
|
||||
Test: cauldron node is full
|
||||
|
||||
|
||||
<h3>Parameters:</h3>
|
||||
<ul>
|
||||
<li><span class="parameter">node</span>
|
||||
Node : Cauldron node description
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3>Returns:</h3>
|
||||
<ol>
|
||||
|
||||
boolean
|
||||
</ol>
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
<dt>
|
||||
<a name = "mcl_cauldrons.is_full"></a>
|
||||
<strong>mcl_cauldrons.is_full (pos)</strong>
|
||||
</dt>
|
||||
<dd>
|
||||
Test: cauldron is full (by position)
|
||||
|
||||
|
||||
<h3>Parameters:</h3>
|
||||
<ul>
|
||||
<li><span class="parameter">pos</span>
|
||||
Position : World position
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3>Returns:</h3>
|
||||
<ol>
|
||||
|
||||
boolean
|
||||
</ol>
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
<dt>
|
||||
<a name = "mcl_cauldrons.node_set_content"></a>
|
||||
<strong>mcl_cauldrons.node_set_content (node, substance, fill_level)</strong>
|
||||
</dt>
|
||||
<dd>
|
||||
Convert cauldron node to satisfy content specifications. </p>
|
||||
|
||||
<p> Cauldron specification is subject to normalization based on substance
|
||||
and fill level (e.g. any substance at level 0 becomes empty cauldron).
|
||||
|
||||
|
||||
<h3>Parameters:</h3>
|
||||
<ul>
|
||||
<li><span class="parameter">node</span>
|
||||
Node : node to have its contents changed
|
||||
</li>
|
||||
<li><span class="parameter">substance</span>
|
||||
string : intended cauldron substance
|
||||
</li>
|
||||
<li><span class="parameter">fill_level</span>
|
||||
number : intended fill level
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3>Returns:</h3>
|
||||
<ol>
|
||||
|
||||
table: new cauldron node
|
||||
</ol>
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
<dt>
|
||||
<a name = "mcl_cauldrons.set_content"></a>
|
||||
<strong>mcl_cauldrons.set_content (pos, substance, fill_level)</strong>
|
||||
</dt>
|
||||
<dd>
|
||||
Place cauldron of specified substance and fill level at world position. </p>
|
||||
|
||||
<p> Cauldron specification is subject to normalization based on substance
|
||||
and fill level (e.g. any substance at level 0 becomes empty cauldron).
|
||||
|
||||
|
||||
<h3>Parameters:</h3>
|
||||
<ul>
|
||||
<li><span class="parameter">pos</span>
|
||||
Position : World position.
|
||||
</li>
|
||||
<li><span class="parameter">substance</span>
|
||||
: string cauldron substance (item def <em>mcl</em>cauldron_substance)
|
||||
</li>
|
||||
<li><span class="parameter">fill_level</span>
|
||||
number : cauldron fill level (typically 0,1,2,3)
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3>Returns:</h3>
|
||||
<ol>
|
||||
|
||||
table: new cauldron node (as passed to minetest.set_pos())
|
||||
</ol>
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
<dt>
|
||||
<a name = "mcl_cauldrons.register_cauldron_node"></a>
|
||||
<strong>mcl_cauldrons.register_cauldron_node (nodename, nodedef, doc_alias)</strong>
|
||||
</dt>
|
||||
<dd>
|
||||
Wrapper to register cauldron-specific nodes.
|
||||
additional bookkeeping specific to mcl_cauldrons.
|
||||
|
||||
|
||||
<h3>Parameters:</h3>
|
||||
<ul>
|
||||
<li><span class="parameter">nodename</span>
|
||||
string : name of node
|
||||
</li>
|
||||
<li><span class="parameter">nodedef</span>
|
||||
table : node description
|
||||
</li>
|
||||
<li><span class="parameter">doc_alias</span>
|
||||
string : for documentation purposes, alias for this specified node name.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
<dt>
|
||||
<a name = "mcl_cauldrons.add_item_proxy"></a>
|
||||
<strong>mcl_cauldrons.add_item_proxy (proxy)</strong>
|
||||
</dt>
|
||||
<dd>
|
||||
Add item proxy class. </p>
|
||||
|
||||
<p> ItemProxy classes expose <code>do_apply()</code> that carries out the duties of
|
||||
<code>on_rightclick()</code> (applying itemstack to cauldron node). This method
|
||||
returns 2 values, a boolean and an ItemStack.
|
||||
The first value is true if no further handling is required (typically
|
||||
interaction is complete), false if it could not handle the interaction.
|
||||
Priority of proxy classes are determined by lateness in <a href="../modules/api.html#mcl_cauldrons.add_item_proxy">add_item_proxy</a> --
|
||||
later additions take priority over earlier ones, allowing for stacked mods
|
||||
to override basal behavior.
|
||||
|
||||
|
||||
<h3>Parameters:</h3>
|
||||
<ul>
|
||||
<li><span class="parameter">proxy</span>
|
||||
ItemProxy : ItemProxy prototype (to have do_apply() invoked on it)
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
<dt>
|
||||
<a name = "mcl_cauldrons.apply_item"></a>
|
||||
<strong>mcl_cauldrons.apply_item (pos, node, user, itemstack)</strong>
|
||||
</dt>
|
||||
<dd>
|
||||
Invoke applying item to cauldron node. </p>
|
||||
|
||||
<p> carry out all the duties of on_rightclick().
|
||||
|
||||
|
||||
<h3>Parameters:</h3>
|
||||
<ul>
|
||||
<li><span class="parameter">pos</span>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
<li><span class="parameter">node</span>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
<li><span class="parameter">user</span>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
<li><span class="parameter">itemstack</span>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3>Returns:</h3>
|
||||
<ol>
|
||||
|
||||
ItemStack: item to be wielded in hand (may be same <code>itemstack</code>).
|
||||
</ol>
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
<h2 class="section-header "><a name="Tables"></a>Tables</h2>
|
||||
|
||||
<dl class="function">
|
||||
<dt>
|
||||
<a name = "mcl_cauldrons.registered_cauldrons"></a>
|
||||
<strong>mcl_cauldrons.registered_cauldrons</strong>
|
||||
</dt>
|
||||
<dd>
|
||||
Table of registered cauldron nodes, indexed by name.
|
||||
Filled by register<em>cauldron</em>node().
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
<dt>
|
||||
<a name = "mcl_cauldrons.substances"></a>
|
||||
<strong>mcl_cauldrons.substances</strong>
|
||||
</dt>
|
||||
<dd>
|
||||
List of recognized substances in cauldron.
|
||||
Filled by register<em>cauldron</em>node()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>See also:</h3>
|
||||
<ul>
|
||||
<a href="../modules/api.html#mcl_cauldrons.list_substances">mcl_cauldrons.list_substances</a>
|
||||
</ul>
|
||||
|
||||
|
||||
</dd>
|
||||
<dt>
|
||||
<a name = "Position"></a>
|
||||
<strong>Position</strong>
|
||||
</dt>
|
||||
<dd>
|
||||
Provided for documentation purposes, frequently-used table format. </p>
|
||||
|
||||
<p> Position in world { x, y, z }
|
||||
|
||||
|
||||
<h3>Fields:</h3>
|
||||
<ul>
|
||||
<li><span class="parameter">x</span>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
<li><span class="parameter">y</span>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
<li><span class="parameter">z</span>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
<dt>
|
||||
<a name = "Node"></a>
|
||||
<strong>Node</strong>
|
||||
</dt>
|
||||
<dd>
|
||||
Provided for documentation purposes, frequently-used table format. </p>
|
||||
|
||||
<p> Node description { name, param1, param2 }, as used by <code>minetest.get_node()</code> and <code>minetest.set_node()</code>
|
||||
(not to be confused with node definition)
|
||||
|
||||
|
||||
<h3>Fields:</h3>
|
||||
<ul>
|
||||
<li><span class="parameter">name</span>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
<li><span class="parameter">param1</span>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
<li><span class="parameter">param2</span>
|
||||
|
||||
|
||||
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
<dt>
|
||||
<a name = "mcl_cauldrons.item_proxies"></a>
|
||||
<strong>mcl_cauldrons.item_proxies</strong>
|
||||
</dt>
|
||||
<dd>
|
||||
List of item proxy classes. </p>
|
||||
|
||||
<p> For item interactions (right-click), handlers for items that may interact
|
||||
with cauldron.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
<h2 class="section-header "><a name="Fields"></a>Fields</h2>
|
||||
|
||||
<dl class="function">
|
||||
<dt>
|
||||
<a name = "mcl_cauldrons.BUCKET_FILL_LEVELS"></a>
|
||||
<strong>mcl_cauldrons.BUCKET_FILL_LEVELS</strong>
|
||||
</dt>
|
||||
<dd>
|
||||
Levels of cauldron change per bucket.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
<dt>
|
||||
<a name = "mcl_cauldrons.BOTTLE_FILL_LEVELS"></a>
|
||||
<strong>mcl_cauldrons.BOTTLE_FILL_LEVELS</strong>
|
||||
</dt>
|
||||
<dd>
|
||||
Levels of cauldron change per bottle (potion).
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
|
||||
</div> <!-- id="content" -->
|
||||
</div> <!-- id="main" -->
|
||||
<div id="about">
|
||||
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
|
||||
<i style="float:right;">Last updated 2021-11-12 11:20:21 </i>
|
||||
</div> <!-- id="about" -->
|
||||
</div> <!-- id="container" -->
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,288 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||
<head>
|
||||
<title>Reference</title>
|
||||
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="container">
|
||||
|
||||
<div id="product">
|
||||
<div id="product_logo"></div>
|
||||
<div id="product_name"><big><b></b></big></div>
|
||||
<div id="product_description"></div>
|
||||
</div> <!-- id="product" -->
|
||||
|
||||
|
||||
<div id="main">
|
||||
|
||||
|
||||
<!-- Menu -->
|
||||
|
||||
<div id="navigation">
|
||||
<br/>
|
||||
<h1>mcl_cauldrons</h1>
|
||||
|
||||
<ul>
|
||||
<li><a href="../index.html">Index</a></li>
|
||||
</ul>
|
||||
|
||||
<h2>Contents</h2>
|
||||
<ul>
|
||||
<li><a href="#Tables">Tables</a></li>
|
||||
<li><a href="#Fields">Fields</a></li>
|
||||
<li><a href="#Local_Functions">Local Functions</a></li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h2>Modules</h2>
|
||||
<ul class="nowrap">
|
||||
<li><a href="../modules/api.html">api</a></li>
|
||||
<li><strong>init</strong></li>
|
||||
<li><a href="../modules/register.html">register</a></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="content">
|
||||
|
||||
<h1>Module <code>init</code></h1>
|
||||
<p>Initialization (primary entry point) for mcl_cauldrons.</p>
|
||||
<p> Adds cauldrons to MineClone2.</p>
|
||||
|
||||
|
||||
<h2><a href="#Tables">Tables</a></h2>
|
||||
<table class="function_list">
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#mcl_cauldrons">mcl_cauldrons</a></td>
|
||||
<td class="summary">Mod namespace.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#MODENV">MODENV</a></td>
|
||||
<td class="summary">mod's environment (preserve references to mod's locals for nested dofile)</td>
|
||||
</tr>
|
||||
</table>
|
||||
<h2><a href="#Fields">Fields</a></h2>
|
||||
<table class="function_list">
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#S">S</a></td>
|
||||
<td class="summary">Common Minetest idiom for text/string translation function.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#modpath">modpath</a></td>
|
||||
<td class="summary">Path of the current Minetest mod.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#modname">modname</a></td>
|
||||
<td class="summary">Name of current mod.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#modpath">modpath</a></td>
|
||||
<td class="summary">Path of current mod.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#mclx_core">mclx_core</a></td>
|
||||
<td class="summary">Path to <a href="../modules/init.html#mclx_core">mclx_core</a> (test <a href="../modules/init.html#mclx_core">mclx_core</a> is loaded)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#has_doc">has_doc</a></td>
|
||||
<td class="summary">Path to <code>doc</code> (test <code>doc</code> is loaded)</td>
|
||||
</tr>
|
||||
</table>
|
||||
<h2><a href="#Local_Functions">Local Functions</a></h2>
|
||||
<table class="function_list">
|
||||
<tr>
|
||||
<td class="name" nowrap><a href="#dosubfile">dosubfile (relpath)</a></td>
|
||||
<td class="summary">Execute dofile using mod's environment.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<br/>
|
||||
<br/>
|
||||
|
||||
|
||||
<h2 class="section-header "><a name="Tables"></a>Tables</h2>
|
||||
|
||||
<dl class="function">
|
||||
<dt>
|
||||
<a name = "mcl_cauldrons"></a>
|
||||
<strong>mcl_cauldrons</strong>
|
||||
</dt>
|
||||
<dd>
|
||||
Mod namespace.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
<dt>
|
||||
<a name = "MODENV"></a>
|
||||
<strong>MODENV</strong>
|
||||
</dt>
|
||||
<dd>
|
||||
mod's environment (preserve references to mod's locals for nested dofile)
|
||||
|
||||
|
||||
<h3>Fields:</h3>
|
||||
<ul>
|
||||
<li><span class="parameter">S</span>
|
||||
Idiomatic function for text translation
|
||||
</li>
|
||||
<li><span class="parameter">modpath</span>
|
||||
path of current mod
|
||||
</li>
|
||||
<li><span class="parameter">modname</span>
|
||||
name of current mod
|
||||
</li>
|
||||
<li><span class="parameter">mclx_core</span>
|
||||
path to mclx_core (<a href="../modules/init.html#mclx_core">mclx_core</a> is loaded)
|
||||
</li>
|
||||
<li><span class="parameter">has_doc</span>
|
||||
path to doc (<code>doc</code> is loaded)
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
<h2 class="section-header "><a name="Fields"></a>Fields</h2>
|
||||
|
||||
<dl class="function">
|
||||
<dt>
|
||||
<a name = "S"></a>
|
||||
<strong>S</strong>
|
||||
</dt>
|
||||
<dd>
|
||||
Common Minetest idiom for text/string translation function.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
<dt>
|
||||
<a name = "modpath"></a>
|
||||
<strong>modpath</strong>
|
||||
</dt>
|
||||
<dd>
|
||||
Path of the current Minetest mod.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
<dt>
|
||||
<a name = "modname"></a>
|
||||
<strong>modname</strong>
|
||||
</dt>
|
||||
<dd>
|
||||
Name of current mod.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
<dt>
|
||||
<a name = "modpath"></a>
|
||||
<strong>modpath</strong>
|
||||
</dt>
|
||||
<dd>
|
||||
Path of current mod.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
<dt>
|
||||
<a name = "mclx_core"></a>
|
||||
<strong>mclx_core</strong>
|
||||
</dt>
|
||||
<dd>
|
||||
Path to <a href="../modules/init.html#mclx_core">mclx_core</a> (test <a href="../modules/init.html#mclx_core">mclx_core</a> is loaded)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
<dt>
|
||||
<a name = "has_doc"></a>
|
||||
<strong>has_doc</strong>
|
||||
</dt>
|
||||
<dd>
|
||||
Path to <code>doc</code> (test <code>doc</code> is loaded)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
<h2 class="section-header "><a name="Local_Functions"></a>Local Functions</h2>
|
||||
|
||||
<dl class="function">
|
||||
<dt>
|
||||
<a name = "dosubfile"></a>
|
||||
<strong>dosubfile (relpath)</strong>
|
||||
</dt>
|
||||
<dd>
|
||||
Execute dofile using mod's environment. </p>
|
||||
|
||||
<p> The environment provided to the the dofile() is that of the current mod's.
|
||||
Present init.lua locals at the same level for other files in this mod.
|
||||
(roughly emulates #include behavior)
|
||||
|
||||
|
||||
<h3>Parameters:</h3>
|
||||
<ul>
|
||||
<li><span class="parameter">relpath</span>
|
||||
string: path to a file under current mod path
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3>Returns:</h3>
|
||||
<ol>
|
||||
|
||||
whatever dofile() returns.
|
||||
</ol>
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
|
||||
</div> <!-- id="content" -->
|
||||
</div> <!-- id="main" -->
|
||||
<div id="about">
|
||||
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
|
||||
<i style="float:right;">Last updated 2021-11-12 11:20:21 </i>
|
||||
</div> <!-- id="about" -->
|
||||
</div> <!-- id="container" -->
|
||||
</body>
|
||||
</html>
|
File diff suppressed because it is too large
Load Diff
|
@ -1,143 +1,66 @@
|
|||
--- Initialization (primary entry point) for mcl_cauldrons.
|
||||
-- Adds cauldrons to MineClone2.
|
||||
|
||||
--- Common Minetest idiom for text/string translation function.
|
||||
local S = minetest.get_translator(minetest.get_current_modname())
|
||||
--- Path of the current Minetest mod.
|
||||
local modpath = minetest.get_modpath(minetest.get_current_modname())
|
||||
|
||||
-- Cauldron mod, adds cauldrons.
|
||||
--- Mod namespace.
|
||||
mcl_cauldrons = {}
|
||||
|
||||
-- TODO: Extinguish fire of burning entities
|
||||
|
||||
-- Convenience function because the cauldron nodeboxes are very similar
|
||||
local create_cauldron_nodebox = function(water_level)
|
||||
local floor_y
|
||||
if water_level == 0 then -- empty
|
||||
floor_y = -0.1875
|
||||
elseif water_level == 1 then -- 1/3 filled
|
||||
floor_y = 1/16
|
||||
elseif water_level == 2 then -- 2/3 filled
|
||||
floor_y = 4/16
|
||||
elseif water_level == 3 then -- full
|
||||
floor_y = 7/16
|
||||
end
|
||||
return {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{-0.5, -0.1875, -0.5, -0.375, 0.5, 0.5}, -- Left wall
|
||||
{0.375, -0.1875, -0.5, 0.5, 0.5, 0.5}, -- Right wall
|
||||
{-0.375, -0.1875, 0.375, 0.375, 0.5, 0.5}, -- Back wall
|
||||
{-0.375, -0.1875, -0.5, 0.375, 0.5, -0.375}, -- Front wall
|
||||
{-0.5, -0.3125, -0.5, 0.5, floor_y, 0.5}, -- Floor
|
||||
{-0.5, -0.5, -0.5, -0.375, -0.3125, -0.25}, -- Left front foot, part 1
|
||||
{-0.375, -0.5, -0.5, -0.25, -0.3125, -0.375}, -- Left front foot, part 2
|
||||
{-0.5, -0.5, 0.25, -0.375, -0.3125, 0.5}, -- Left back foot, part 1
|
||||
{-0.375, -0.5, 0.375, -0.25, -0.3125, 0.5}, -- Left back foot, part 2
|
||||
{0.375, -0.5, 0.25, 0.5, -0.3125, 0.5}, -- Right back foot, part 1
|
||||
{0.25, -0.5, 0.375, 0.375, -0.3125, 0.5}, -- Right back foot, part 2
|
||||
{0.375, -0.5, -0.5, 0.5, -0.3125, -0.25}, -- Right front foot, part 1
|
||||
{0.25, -0.5, -0.5, 0.375, -0.3125, -0.375}, -- Right front foot, part 2
|
||||
}
|
||||
--- Name of current mod.
|
||||
local modname = minetest.get_current_modname()
|
||||
--- Path of current mod.
|
||||
local modpath = minetest.get_modpath(modname)
|
||||
--- Path to `mclx_core` (test `mclx_core` is loaded)
|
||||
local mclx_core = minetest.get_modpath("mclx_core")
|
||||
--- Path to `doc` (test `doc` is loaded)
|
||||
local has_doc = minetest.get_modpath("doc")
|
||||
--- mod's environment (preserve references to mod's locals for nested dofile)
|
||||
-- @field S Idiomatic function for text translation
|
||||
-- @field modpath path of current mod
|
||||
-- @field modname name of current mod
|
||||
-- @field mclx_core path to mclx_core (`mclx_core` is loaded)
|
||||
-- @field has_doc path to doc (`doc` is loaded)
|
||||
local MODENV = {
|
||||
S = S,
|
||||
modpath = modpath,
|
||||
modname = modname,
|
||||
mclx_core = mclx_core,
|
||||
has_doc = has_doc,
|
||||
}
|
||||
MODENV.MODENV = MODENV
|
||||
setmetatable(MODENV, {__index=_G}) -- chain to global.
|
||||
|
||||
--- Execute dofile using mod's environment.
|
||||
--
|
||||
-- The environment provided to the the dofile() is that of the current mod's.
|
||||
-- Present init.lua locals at the same level for other files in this mod.
|
||||
-- (roughly emulates #include behavior)
|
||||
--
|
||||
-- @param relpath string: path to a file under current mod path
|
||||
-- @return whatever dofile() returns.
|
||||
local function dosubfile(relpath)
|
||||
-- present mod-local environment to nested subfile.
|
||||
if setfenv then
|
||||
-- Lua 5.1
|
||||
local submodule, err = loadfile(modpath .. "/" .. relpath)
|
||||
if err then
|
||||
error(err)
|
||||
end
|
||||
|
||||
local cauldron_nodeboxes = {}
|
||||
for w=0,3 do
|
||||
cauldron_nodeboxes[w] = create_cauldron_nodebox(w)
|
||||
end
|
||||
|
||||
|
||||
-- Empty cauldron
|
||||
minetest.register_node("mcl_cauldrons:cauldron", {
|
||||
description = S("Cauldron"),
|
||||
_tt_help = S("Stores water"),
|
||||
_doc_items_longdesc = S("Cauldrons are used to store water and slowly fill up under rain."),
|
||||
_doc_items_usagehelp = S("Place a water bucket into the cauldron to fill it with water. Place an empty bucket on a full cauldron to retrieve the water. Place a water bottle into the cauldron to fill the cauldron to one third with water. Place a glass bottle in a cauldron with water to retrieve one third of the water."),
|
||||
wield_image = "mcl_cauldrons_cauldron.png",
|
||||
inventory_image = "mcl_cauldrons_cauldron.png",
|
||||
use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or false,
|
||||
drawtype = "nodebox",
|
||||
paramtype = "light",
|
||||
is_ground_content = false,
|
||||
groups = {pickaxey=1, deco_block=1, cauldron=1},
|
||||
node_box = cauldron_nodeboxes[0],
|
||||
selection_box = { type = "regular" },
|
||||
tiles = {
|
||||
"mcl_cauldrons_cauldron_inner.png^mcl_cauldrons_cauldron_top.png",
|
||||
"mcl_cauldrons_cauldron_inner.png^mcl_cauldrons_cauldron_bottom.png",
|
||||
"mcl_cauldrons_cauldron_side.png"
|
||||
},
|
||||
sounds = mcl_sounds.node_sound_metal_defaults(),
|
||||
_mcl_hardness = 2,
|
||||
_mcl_blast_resistance = 2,
|
||||
})
|
||||
|
||||
-- Template function for cauldrons with water
|
||||
local register_filled_cauldron = function(water_level, description, river_water)
|
||||
local id = "mcl_cauldrons:cauldron_"..water_level
|
||||
local water_tex
|
||||
if river_water then
|
||||
id = id .. "r"
|
||||
water_tex = "default_river_water_source_animated.png^[verticalframe:16:0"
|
||||
setfenv(submodule, MODENV)
|
||||
return submodule()
|
||||
else
|
||||
water_tex = "default_water_source_animated.png^[verticalframe:16:0"
|
||||
end
|
||||
minetest.register_node(id, {
|
||||
description = description,
|
||||
_doc_items_create_entry = false,
|
||||
use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or false,
|
||||
drawtype = "nodebox",
|
||||
paramtype = "light",
|
||||
is_ground_content = false,
|
||||
groups = {pickaxey=1, not_in_creative_inventory=1, cauldron=(1+water_level), cauldron_filled=water_level, comparator_signal=water_level},
|
||||
node_box = cauldron_nodeboxes[water_level],
|
||||
collision_box = cauldron_nodeboxes[0],
|
||||
selection_box = { type = "regular" },
|
||||
tiles = {
|
||||
"("..water_tex..")^mcl_cauldrons_cauldron_top.png",
|
||||
"mcl_cauldrons_cauldron_inner.png^mcl_cauldrons_cauldron_bottom.png",
|
||||
"mcl_cauldrons_cauldron_side.png"
|
||||
},
|
||||
sounds = mcl_sounds.node_sound_metal_defaults(),
|
||||
drop = "mcl_cauldrons:cauldron",
|
||||
_mcl_hardness = 2,
|
||||
_mcl_blast_resistance = 2,
|
||||
})
|
||||
|
||||
-- Add entry aliases for the Help
|
||||
if minetest.get_modpath("doc") then
|
||||
doc.add_entry_alias("nodes", "mcl_cauldrons:cauldron", "nodes", id)
|
||||
-- Lua 5.2+
|
||||
return dofile(modpath .. "/" .. relpath, "bt", MODENV)
|
||||
end
|
||||
end
|
||||
|
||||
-- Filled cauldrons (3 levels)
|
||||
register_filled_cauldron(1, S("Cauldron (1/3 Water)"))
|
||||
register_filled_cauldron(2, S("Cauldron (2/3 Water)"))
|
||||
register_filled_cauldron(3, S("Cauldron (3/3 Water)"))
|
||||
MODENV.dosubfile = dosubfile
|
||||
|
||||
if minetest.get_modpath("mclx_core") then
|
||||
register_filled_cauldron(1, S("Cauldron (1/3 River Water)"), true)
|
||||
register_filled_cauldron(2, S("Cauldron (2/3 River Water)"), true)
|
||||
register_filled_cauldron(3, S("Cauldron (3/3 River Water)"), true)
|
||||
end
|
||||
|
||||
minetest.register_craft({
|
||||
output = "mcl_cauldrons:cauldron",
|
||||
recipe = {
|
||||
{ "mcl_core:iron_ingot", "", "mcl_core:iron_ingot" },
|
||||
{ "mcl_core:iron_ingot", "", "mcl_core:iron_ingot" },
|
||||
{ "mcl_core:iron_ingot", "mcl_core:iron_ingot", "mcl_core:iron_ingot" },
|
||||
}
|
||||
})
|
||||
dofile(modpath.."/api.lua")
|
||||
dosubfile("register.lua")
|
||||
|
||||
minetest.register_abm({
|
||||
label = "cauldrons",
|
||||
nodenames = {"group:cauldron_filled"},
|
||||
interval = 0.5,
|
||||
chance = 1,
|
||||
action = function(pos, node)
|
||||
for _, obj in pairs(minetest.get_objects_inside_radius(pos, 0.4)) do
|
||||
if mcl_burning.is_burning(obj) then
|
||||
mcl_burning.extinguish(obj)
|
||||
local new_group = minetest.get_item_group(node.name, "cauldron_filled") - 1
|
||||
minetest.swap_node(pos, {name = "mcl_cauldrons:cauldron" .. (new_group == 0 and "" or "_" .. new_group)})
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
})
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
name = mcl_cauldrons
|
||||
depends = mcl_core, mcl_sounds
|
||||
optional_depends = mclx_core, doc
|
||||
description = Add cauldrons to mcl
|
||||
depends = mcl_core, mcl_sounds, mcl_buckets
|
||||
optional_depends = mclx_core, doc, mcl_potions
|
||||
|
|
|
@ -0,0 +1,699 @@
|
|||
--- Base cauldron types.
|
||||
|
||||
--local S = minetest.get_translator(minetest.get_current_modname())
|
||||
-- expected to be provided by setfenv/environment.
|
||||
|
||||
|
||||
-- Convenience function because the cauldron nodeboxes are very similar
|
||||
local floors_table = {
|
||||
[0]=-0.1875, -- empty
|
||||
[1]=1/16, -- 1/3 filled
|
||||
[2]=4/16, -- 2/3 filled
|
||||
[3]=7/16, -- full
|
||||
}
|
||||
|
||||
local create_cauldron_nodebox = function(water_level)
|
||||
local floor_y = floors_table[water_level]
|
||||
return {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{-0.5, -0.1875, -0.5, -0.375, 0.5, 0.5}, -- Left wall
|
||||
{0.375, -0.1875, -0.5, 0.5, 0.5, 0.5}, -- Right wall
|
||||
{-0.375, -0.1875, 0.375, 0.375, 0.5, 0.5}, -- Back wall
|
||||
{-0.375, -0.1875, -0.5, 0.375, 0.5, -0.375}, -- Front wall
|
||||
{-0.5, -0.3125, -0.5, 0.5, floor_y, 0.5}, -- Floor
|
||||
{-0.5, -0.5, -0.5, -0.375, -0.3125, -0.25}, -- Left front foot, part 1
|
||||
{-0.375, -0.5, -0.5, -0.25, -0.3125, -0.375}, -- Left front foot, part 2
|
||||
{-0.5, -0.5, 0.25, -0.375, -0.3125, 0.5}, -- Left back foot, part 1
|
||||
{-0.375, -0.5, 0.375, -0.25, -0.3125, 0.5}, -- Left back foot, part 2
|
||||
{0.375, -0.5, 0.25, 0.5, -0.3125, 0.5}, -- Right back foot, part 1
|
||||
{0.25, -0.5, 0.375, 0.375, -0.3125, 0.5}, -- Right back foot, part 2
|
||||
{0.375, -0.5, -0.5, 0.5, -0.3125, -0.25}, -- Right front foot, part 1
|
||||
{0.25, -0.5, -0.5, 0.375, -0.3125, -0.375}, -- Right front foot, part 2
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
-- Generate nodeboxes for cauldrons, (0=empty, 1=1/3 filled, 2=2/3 filled, 3=full)
|
||||
mcl_cauldrons.cauldron_nodeboxes = {}
|
||||
for w=0,3 do
|
||||
mcl_cauldrons.cauldron_nodeboxes[w] = create_cauldron_nodebox(w)
|
||||
end
|
||||
|
||||
|
||||
--- Merge tables of declarative objects.
|
||||
--
|
||||
-- The normal Lua means of inheritance uses setmetatable.
|
||||
-- For node definitions, minetest.register_node() breaks/overwrite the metatable for its own use.
|
||||
-- This function copies in the "old" keys/values, to let them be overwritten by another (newer) table.
|
||||
-- Nested tables are recursively merged/copied, so nested keys may be selectively overridden.
|
||||
-- Modifying the returned table does not risk mangling the source/parent table.
|
||||
-- This workaround happens to work as declarative objects do not change after instantiation.
|
||||
--
|
||||
-- @return recursively-merged table of first and second arguments
|
||||
local function merge_tables(a,b)
|
||||
local result = {}
|
||||
for k,v in pairs(a) do result[k]=v end
|
||||
for k,v in pairs(b) do
|
||||
if type(a[k]) == "table" then
|
||||
-- recursive merge table (with copy).
|
||||
result[k] = merge_tables(a[k], v)
|
||||
else
|
||||
result[k] = v
|
||||
end
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
MODENV.merge_tables = merge_tables
|
||||
|
||||
|
||||
--------
|
||||
--------
|
||||
|
||||
local ItemProxy = {}
|
||||
|
||||
--- Item Proxy (base prototype).
|
||||
--
|
||||
-- Interaction with items are done through a proxy that presume certain
|
||||
-- behaviors of actual/registered items.
|
||||
-- The idea is to avoid invoking mod-specific functions by name
|
||||
-- (therefore relying on callbacks from node definition),
|
||||
-- as mods may be extend, replace, or disable items.
|
||||
--
|
||||
-- Initial item proxies include:
|
||||
--
|
||||
-- * BucketProxy - interacting with bucket-like items (change fill level by 3)
|
||||
-- * BottleProxy - interacting with bottle-like items (change fill level by 1)
|
||||
-- * BannerProxy - banner-like items (wash banner, deplete 1 level)
|
||||
mcl_cauldrons.ItemProxy = ItemProxy
|
||||
|
||||
function ItemProxy.__call(self, ...)
|
||||
local child = {
|
||||
__index = self,
|
||||
__call = self.__call,
|
||||
rules = {},
|
||||
}
|
||||
setmetatable(child, child)
|
||||
return child
|
||||
end
|
||||
setmetatable(ItemProxy, ItemProxy)
|
||||
|
||||
--- Handle applying (right-clicking) item to cauldron node.
|
||||
--
|
||||
-- delegated by do_rightclick()
|
||||
-- @param pos Position : position of (cauldron) node
|
||||
-- @param node Node : cauldron node description
|
||||
-- @param user UserRef : user using the item on cauldron node
|
||||
-- @param itemstack ItemStack : item wielded by user
|
||||
-- @return 2-value: apply succeded (boolean), itemstack to go in hand (ItemStack, may be same `itemstack`)
|
||||
function ItemProxy:do_apply(pos, node, user, itemstack)
|
||||
local newnode, newitemstack, sound_specifier
|
||||
newnode, newitemstack, sound_specifier = self:apply_basic_rules(itemstack, node)
|
||||
if not newnode and not newitemstack then
|
||||
return false
|
||||
end
|
||||
-- TODO: fix the redundancy
|
||||
local held_itemstack = self:common_exchange(pos, newnode, user, itemstack, newitemstack)
|
||||
if sound_specifier then
|
||||
local soundspec
|
||||
local soundparm = {}
|
||||
if type(sound_specifier) == "function" then
|
||||
local spec_parm
|
||||
soundspec, spec_parm = sound_specifier(self, newitemstack, node)
|
||||
if not soundspec then return true, held_itemstack end -- shortcut
|
||||
if spec_parm then
|
||||
soundparm = table.copy(spec_parm)
|
||||
end
|
||||
else
|
||||
soundspec = sound_specifier
|
||||
end
|
||||
if soundspec then
|
||||
-- update position.
|
||||
soundparm.pos = pos
|
||||
minetest.sound_play(soundspec, soundparm, true)
|
||||
end
|
||||
end
|
||||
return true, held_itemstack
|
||||
end
|
||||
|
||||
|
||||
|
||||
--------
|
||||
--------
|
||||
|
||||
local RuleBasedItemProxy = ItemProxy()
|
||||
|
||||
--- Item Proxy interaction with cauldron defined by rulesets.
|
||||
mcl_cauldrons.RuleBasedItemProxy = RuleBasedItemProxy
|
||||
|
||||
--- prototype derivation to keep separate .rules
|
||||
function RuleBasedItemProxy.__call(self, ...)
|
||||
local child = {
|
||||
__index = self,
|
||||
__call = self.__call,
|
||||
rules = {},
|
||||
}
|
||||
setmetatable(child, child)
|
||||
return child
|
||||
end
|
||||
|
||||
function RuleBasedItemProxy.add_basic_rule(self, match_substance, match_level, input_constraint, next_substance, next_level, output_specifier, sound_specifier)
|
||||
end
|
||||
|
||||
--- common one-for-one item exchange
|
||||
--
|
||||
-- put new_node at pos, and in exchange take 1 from itemstack, and give 1 of new_item to user.
|
||||
-- @return ItemStack: new itemstack to replace `itemstack` (may be itself with changes)
|
||||
function RuleBasedItemProxy.common_exchange(self, pos, new_node, user, itemstack, new_itemstack)
|
||||
if new_node ~= nil then
|
||||
minetest.set_node(pos, new_node)
|
||||
end
|
||||
if type(new_itemstack) == "string" then
|
||||
new_itemstack = ItemStack(new_itemstack)
|
||||
end
|
||||
if new_itemstack ~= nil then
|
||||
if minetest.is_creative_enabled(user:get_player_name()) then
|
||||
-- creative inventory: add new_itemstack if missing.
|
||||
local inv = user:get_inventory()
|
||||
if not inv:contains_item("main", new_itemstack) then
|
||||
inv:add_item("main", new_itemstack)
|
||||
end
|
||||
else
|
||||
-- survival.
|
||||
if itemstack:get_count() == 1 then
|
||||
-- swap with new item.
|
||||
return new_itemstack
|
||||
else
|
||||
-- subtract one, deposit new_itemstack
|
||||
itemstack:take_item(1)
|
||||
local inv = user:get_inventory()
|
||||
if inv:room_for_item("main", new_itemstack) then
|
||||
-- add to inventory
|
||||
inv:add_item("main", new_itemstack)
|
||||
else
|
||||
-- drop on ground.
|
||||
minetest.add_item(user:get_pos(), new_itemstack)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return itemstack
|
||||
end
|
||||
|
||||
--- Add item/cauldron exchange rule.
|
||||
--
|
||||
-- Rule following the basic cauldron fill/empty and bucket fill/empty pattern:
|
||||
--
|
||||
-- * cauldron consistes of a particular substance and specific level.
|
||||
-- * cauldron turns into one of a particular substance and level.
|
||||
-- * the one bucket used turns into one bucket of something else.
|
||||
--
|
||||
-- @param match_substance string : cauldron substance matching this rule (nil means empty)
|
||||
-- @param match_level number : cauldron fill level matching this rule (nil means any, true maps to full)
|
||||
-- @param input_constraint
|
||||
-- * string => exact match with item name to trigger rule.
|
||||
-- * function(ItemStack) => predicate given item stack, to trigger rule.
|
||||
-- @param next_substance string : new cauldron content (nil means empty)
|
||||
-- @param next_level number : new cauldron fill level (true means full, 0 means empty)
|
||||
-- @param output_specifier
|
||||
-- * string => specific item name to generate after successful rule match
|
||||
-- * function(ItemStack, table) => given old item stack and new cauldron node, generate new item stack on rule match
|
||||
-- @param sound_specifier
|
||||
-- * string => specific item name to play 'place' sound on match rule.
|
||||
-- * function(ItemStack, table) => given ItemStack and new cauldron node, return (soundspec, soundparam)
|
||||
|
||||
function RuleBasedItemProxy:add_basic_rule(match_substance, match_level, input_constraint, next_substance, next_level, output_specifier, sound_specifier)
|
||||
local rule = {
|
||||
match_substance = match_substance,
|
||||
match_level = match_level,
|
||||
input_constraint = input_constraint,
|
||||
next_substance = next_substance,
|
||||
next_level = next_level,
|
||||
output_specifier = output_specifier,
|
||||
sound_specifier = sound_specifier,
|
||||
}
|
||||
table.insert(self.rules, rule)
|
||||
end
|
||||
|
||||
-- helper function for determining if a rule matches.
|
||||
function RuleBasedItemProxy:_rule_match(rule, itemstack, cauldron_node)
|
||||
if rule.match_substance ~= mcl_cauldrons.node_get_substance(cauldron_node) then
|
||||
return
|
||||
end
|
||||
if rule.match_level ~= nil then
|
||||
local current_level = mcl_cauldrons.node_get_level(cauldron_node)
|
||||
-- `true` as alias for maximum.
|
||||
if rule.match_level == true then
|
||||
if current_level ~= mcl_cauldrons.BUCKET_FILL_LEVELS then
|
||||
return
|
||||
end
|
||||
elseif current_level ~= rule.match_level then
|
||||
return
|
||||
end
|
||||
end
|
||||
-- else match any level.
|
||||
if type(rule.input_constraint) == "string" then
|
||||
-- require exact string match.
|
||||
if itemstack:get_name() ~= rule.input_constraint then return end
|
||||
elseif type(rule.input_constraint) == "function" then
|
||||
-- require item predicate.
|
||||
if not rule.input_constraint(itemstack) then return end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
--- Apply basic rules with given ItemStack and cauldron node.
|
||||
--
|
||||
-- apply basic (patterned) rules to the provided item stack and cauldron node.
|
||||
-- @return 3-value: new cauldron node table, new item stack, sound_specifier
|
||||
function RuleBasedItemProxy:apply_basic_rules(itemstack, cauldron_node)
|
||||
local match_rule
|
||||
for i, rule in ipairs(self.rules) do
|
||||
if self:_rule_match(rule, itemstack, cauldron_node) then
|
||||
match_rule = rule
|
||||
break
|
||||
end
|
||||
end
|
||||
if not match_rule then return end
|
||||
-- cauldron transition.
|
||||
local next_level = match_rule.next_level
|
||||
if next_level == true then
|
||||
-- `true` as alias for maximum.
|
||||
next_level = mcl_cauldrons.BUCKET_FILL_LEVELS
|
||||
end
|
||||
local newnode = mcl_cauldrons.node_set_content(cauldron_node, match_rule.next_substance, next_level)
|
||||
local newitemstack
|
||||
if type(match_rule.output_specifier) == "string" then
|
||||
-- one particular item
|
||||
newitemstack = ItemStack(match_rule.output_specifier)
|
||||
elseif type(match_rule.output_specifier) == "function" then
|
||||
-- function.
|
||||
newitemstack = match_rule.output_specifier(itemstack, newnode)
|
||||
end
|
||||
return newnode, newitemstack, match_rule.sound_specifier
|
||||
end
|
||||
|
||||
|
||||
|
||||
-------
|
||||
-------
|
||||
|
||||
-- Bucket(-like) item proxy.
|
||||
|
||||
local BucketProxy = mcl_cauldrons.RuleBasedItemProxy()
|
||||
|
||||
--- Bucket-like interaction with cauldron.
|
||||
--
|
||||
-- * empty bucket: requires full cauldron, produce something bucket, cauldron becomes empty.
|
||||
-- * something bucket: requires empty cauldron, produce empty bucket, cauldron becomes full.
|
||||
-- * something bucket: requires compatible-liquid cauldron, produce empty bucket, cauldron becomes full.
|
||||
mcl_cauldrons.BucketProxy = BucketProxy
|
||||
|
||||
-- TODO: expand mcl_buckets node definitions to avoid relying on name matching.
|
||||
|
||||
--- Rule's `input_constraint` callback for empty bucket.
|
||||
-- @param itemstack ItemStack : item stack to test.
|
||||
function BucketProxy.is_empty(itemstack)
|
||||
if (itemstack:get_name() == "mcl_buckets:bucket_empty") then return true end
|
||||
-- other tests.
|
||||
end
|
||||
|
||||
--- Rule's `input_constraint` callback for water bucket.
|
||||
-- @param itemstack ItemStack : item stack to test.
|
||||
function BucketProxy.is_water(itemstack)
|
||||
if (itemstack:get_name() == "mcl_buckets:bucket_water") then return true end
|
||||
-- other tests.
|
||||
end
|
||||
|
||||
|
||||
--- Rule's `sound_specifier` method for water bucket use.
|
||||
-- @param new_itemstack ItemStack : item stack produced due to rule match
|
||||
-- @param new_cauldron_node Node : cauldron node produced due to rule match
|
||||
-- @return 2-value: sound specifier, sound parameter
|
||||
function BucketProxy:sound_water(new_itemstack, new_cauldron_node)
|
||||
-- water bucket.
|
||||
local nodedef = minetest.registered_nodes["mcl_core:water_source"]
|
||||
if self.is_empty(new_itemstack) then
|
||||
-- water placed.
|
||||
return nodedef.sounds.place, { pitch = 1 + math.random(-10, 10) * .005 }
|
||||
else
|
||||
-- water taken.
|
||||
return nodedef.sounds.dug, { pitch = 1 + math.random(-10, 10) * .005 }
|
||||
end
|
||||
end
|
||||
|
||||
--- Rule's `output_specifier` callback for obtaining an empty bucket.
|
||||
-- @param old_itemstack ItemStack : item stack provided as input
|
||||
-- @param cauldron_node Node : cauldron node produced due to rule match.
|
||||
-- @return ItemStack: item stack to be wielded by user
|
||||
function BucketProxy.make_empty(old_itemstack, cauldron_node)
|
||||
-- TODO: scan registered items for first matching "empty bucket" criteria
|
||||
for scan_name, scan_def in pairs(minetest.registered_items) do
|
||||
-- TODO: expand mcl_buckets node definitions.
|
||||
end
|
||||
end
|
||||
|
||||
--- Rule's `output_specifier` callback for obtaining a water bucket.
|
||||
-- @param old_itemstack ItemStack : item stack provided as input
|
||||
-- @param cauldron_node Node : cauldron node produced due to rule match.
|
||||
-- @return ItemStack: item stack to be wielded by user
|
||||
function BucketProxy.make_water(old_itemstack, cauldron_node)
|
||||
-- TODO: scan registered items for first matching "empty bucket" criteria
|
||||
for scan_name, scan_def in pairs(minetest.registered_items) do
|
||||
-- TODO: expand mcl_buckets node definitions.
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--- Patterned bucket rules.
|
||||
--
|
||||
-- Buckets fill to full, empty from full.
|
||||
-- @param substance string : substance shared between bucket and cauldron
|
||||
-- @param filled_input string/function : filled bucket given to cauldron
|
||||
-- @param filled_output string/function : filled bucket taken from cauldron
|
||||
-- @param sound_specifier string/function : rule's sound specifier
|
||||
function BucketProxy:add_bucket_rules(substance, filled_input, filled_output, sound_specifier)
|
||||
local empty = "mcl_buckets:bucket_empty"
|
||||
local empty_output = "mcl_buckets:bucket_empty"
|
||||
-- full stuff cauldron + empty bucket -> empty cauldron, full bucket
|
||||
self:add_basic_rule(substance, true, empty, nil, 0, filled_output, sound_specifier)
|
||||
-- any level stuff cauldron + stuff bucket -> full stuff cauldron, empty bucket (may waste bucket)
|
||||
self:add_basic_rule(substance, nil, filled_input, substance, true, empty_output, sound_specifier)
|
||||
-- empty cauldron + stuff bucket -> full stuff cauldron, empty bucket
|
||||
self:add_basic_rule(nil, 0, filled_input, substance, true, empty_output, sound_specifier)
|
||||
-- other combinations -> do nothing (no interaction)
|
||||
end
|
||||
|
||||
|
||||
BucketProxy:add_bucket_rules("water", BucketProxy.is_water, "mcl_buckets:bucket_water", BucketProxy.sound_water)
|
||||
|
||||
|
||||
-------
|
||||
-------
|
||||
|
||||
-- Bottle(-like) item proxy.
|
||||
|
||||
local BottleProxy = mcl_cauldrons.RuleBasedItemProxy()
|
||||
|
||||
--- Bottle-like interaction with Cauldron.
|
||||
--
|
||||
-- * empty bottle: requires non-empty cauldron, generate something bottle, reduce cauldron level by 1.
|
||||
-- * something bottle: empty cauldron or same-liquid cauldron, generate empty bottle, increase cauldron level by 1.
|
||||
mcl_cauldrons.BottleProxy = BottleProxy
|
||||
|
||||
-- TODO: expand mcl_potions to avoid relying on name comparisons.
|
||||
|
||||
--- Rule's `input_constraint` callback for empty bottle.
|
||||
-- @param itemstack ItemStack : item stack to test.
|
||||
-- @return boolean
|
||||
function BottleProxy.is_empty(itemstack)
|
||||
if (itemstack:get_name() == "mcl_potions:glass_bottle") then return true end
|
||||
-- other tests.
|
||||
end
|
||||
|
||||
--- Rule's `input_constraint` callback for water bottle.
|
||||
-- @param itemstack ItemStack : item stack to test.
|
||||
-- @return boolean
|
||||
function BottleProxy.is_water(itemstack)
|
||||
if (itemstack:get_name() == "mcl_potions:water") then return true end
|
||||
-- other tests.
|
||||
end
|
||||
|
||||
--- Rule's `sound_specifier` method for water bottle use.
|
||||
-- @param new_itemstack ItemStack : item stack produced from rule matching
|
||||
-- @param new_cauldron_node Node : cauldron node produced from rule matching
|
||||
-- @return 2-value: sound specifier, sound parameter
|
||||
function BottleProxy:sound_water(new_itemstack, new_cauldron_node)
|
||||
if self.is_empty(new_itemstack) then
|
||||
return "mcl_potions_bottle_pour"
|
||||
else
|
||||
return "mcl_potions_bottle_fill"
|
||||
end
|
||||
end
|
||||
|
||||
--- Rule's `output_specifier` function for obtaining empty bottle.
|
||||
-- @param old_itemstack ItemStack : item stack as input to rule matching
|
||||
-- @param cauldron_node Node : cauldron node produced from rule matching
|
||||
-- @return ItemStack: item stack to be wielded by user
|
||||
function BottleProxy.make_empty(old_itemstack, cauldron_node)
|
||||
return ItemStack("mcl_potions:glass_bottle")
|
||||
end
|
||||
|
||||
--- Rule's `output_specifier` function for obtaining water bottle.
|
||||
-- @param old_itemstack ItemStack : item stack as input to rule matching
|
||||
-- @param cauldron_node Node : cauldron node produced from rule matching
|
||||
-- @return ItemStack: item stack to be wielded by user
|
||||
function BottleProxy.make_water(old_itemstack, cauldron_node)
|
||||
return ItemStack("mcl_potions:water")
|
||||
end
|
||||
|
||||
--- Patterned bottle rules.
|
||||
--
|
||||
-- Bottles fill by 1 level, drain by 1 level, not wasted on full cauldron.
|
||||
-- @param substance string : substance shared between bottle and cauldron.
|
||||
-- @param filled_input string/function : filled bottle given to cauldron
|
||||
-- @param filled_output string/function : filled bottle taken from cauldron
|
||||
-- @param sound_specifier string/function : rule's sound specifier
|
||||
function BottleProxy:add_bottle_rules(substance, filled_input, filled_output, sound_specifier)
|
||||
local empty_input = self.is_empty
|
||||
local empty_output = self.make_empty
|
||||
-- stuff cauldron + empty bottle -> stuff cauldron less 1, water bottle
|
||||
self:add_basic_rule(substance, 3, empty_input, substance, 2, filled_output, sound_specifier)
|
||||
self:add_basic_rule(substance, 2, empty_input, substance, 1, filled_output, sound_specifier)
|
||||
self:add_basic_rule(substance, 1, empty_input, nil, 0, filled_output, sound_specifier)
|
||||
-- empty cauldron + stuff bottle -> stuff cauldron 1, empty bottle
|
||||
self:add_basic_rule(nil, 0, filled_input, substance, 1, empty_output, sound_specifier)
|
||||
-- stuff cauldron + stuff bottle -> stuff cauldron plus 1, empty bottle
|
||||
self:add_basic_rule(substance, 1, filled_input, substance, 2, empty_output, sound_specifier)
|
||||
self:add_basic_rule(substance, 2, filled_input, substance, 3, empty_output, sound_specifier)
|
||||
-- full cauldron + stuff bottle -> do nothing (do not waste bottle)
|
||||
end
|
||||
|
||||
|
||||
BottleProxy:add_bottle_rules("water", BottleProxy.is_water, BottleProxy.make_water, BottleProxy.sound_water)
|
||||
|
||||
|
||||
-------
|
||||
-------
|
||||
|
||||
-- Banner item proxy
|
||||
|
||||
local BannerProxy = mcl_cauldrons.RuleBasedItemProxy()
|
||||
|
||||
--- Banner-like interaction with Cauldron.
|
||||
--
|
||||
-- * Apply to water cauldron to wash topmost layer.
|
||||
-- * Applying causes water cauldron to drop 1 level.
|
||||
mcl_cauldrons.BannerProxy = BannerProxy
|
||||
|
||||
-- TODO: better predicate tests
|
||||
|
||||
--- Rule's `input_constraint` function for banner.
|
||||
-- @param itemstack ItemStack : item stack to test.
|
||||
-- @return boolean
|
||||
function BannerProxy.is_banner(itemstack)
|
||||
if string.sub(itemstack:get_name(), 1, 12) == "mcl_banners:" then
|
||||
return true
|
||||
end
|
||||
-- other tests.
|
||||
end
|
||||
|
||||
--- Rule's `output_specifier` function for obtaining washed banner.
|
||||
--
|
||||
-- In the case of banners, the resulting itemstack is the old itemstack with metadata modification (handled by on_wash()).
|
||||
-- @param old_itemstack ItemStack : item stack that was input to rule matching.
|
||||
-- @param cauldron_node Node : cauldron node produced from rule matching.
|
||||
-- @return ItemStack: to be the item wielded by user
|
||||
function BannerProxy.wash_banner(old_itemstack, cauldron_node)
|
||||
local nodedef = old_itemstack:get_definition()
|
||||
local washed_itemstack
|
||||
if nodedef._mcl_on_wash then
|
||||
washed_itemstack = nodedef._mcl_on_wash(old_itemstack)
|
||||
else
|
||||
washed_itemstack = old_itemstack
|
||||
end
|
||||
return washed_itemstack
|
||||
end
|
||||
|
||||
|
||||
--- Patterned banner rules.
|
||||
--
|
||||
-- Banner washed in cauldron, reduces by 1 level, may waste washing (blank banner washable)
|
||||
-- @param substance string : substance consumed from cauldron
|
||||
-- @param sound_specifier string/function : rule's sound specifier
|
||||
function BannerProxy:add_banner_rules(substance, sound_specifier)
|
||||
self:add_basic_rule(substance, 3, self.is_banner, substance, 2, self.wash_banner, sound_specifier)
|
||||
self:add_basic_rule(substance, 2, self.is_banner, substance, 1, self.wash_banner, sound_specifier)
|
||||
self:add_basic_rule(substance, 1, self.is_banner, nil, 0, self.wash_banner, sound_specifier)
|
||||
end
|
||||
|
||||
|
||||
BannerProxy:add_banner_rules("water", "mcl_potions_bottle_pour")
|
||||
|
||||
|
||||
|
||||
--------
|
||||
--------
|
||||
|
||||
|
||||
|
||||
|
||||
-- initial item proxies.
|
||||
-- FIXME: I don't like where this is buried, considering how crucial it is to enabling item interaction. -PH
|
||||
mcl_cauldrons.add_item_proxy(mcl_cauldrons.BannerProxy)
|
||||
if minetest.get_modpath("mcl_potions") then
|
||||
mcl_cauldrons.add_item_proxy(mcl_cauldrons.BottleProxy)
|
||||
end
|
||||
mcl_cauldrons.add_item_proxy(mcl_cauldrons.BucketProxy)
|
||||
|
||||
|
||||
|
||||
|
||||
--------
|
||||
--------
|
||||
|
||||
|
||||
|
||||
|
||||
--- Empty cauldron node definition
|
||||
-- @name mcl_cauldrons:cauldron
|
||||
-- @class table
|
||||
mcl_cauldrons.register_cauldron_node("mcl_cauldrons:cauldron", {
|
||||
description = S("Cauldron"),
|
||||
_tt_help = S("Stores water"),
|
||||
_doc_items_longdesc = S("Cauldrons are used to store water and slowly fill up under rain."),
|
||||
_doc_items_usagehelp = S("Place a water pucket into the cauldron to fill it with water. Place an empty bucket on a full cauldron to retrieve the water. Place a water bottle into the cauldron to fill the cauldron to one third with water. Place a glass bottle in a cauldron with water to retrieve one third of the water."),
|
||||
wield_image = "mcl_cauldrons_cauldron.png",
|
||||
inventory_image = "mcl_cauldrons_cauldron.png",
|
||||
use_texture_alpha = minetest.features.use_texture_alpha_string_modes and "opaque" or false,
|
||||
drawtype = "nodebox",
|
||||
paramtype = "light",
|
||||
is_ground_content = false,
|
||||
groups = {pickaxey=1, deco_block=1, cauldron=1},
|
||||
node_box = mcl_cauldrons.cauldron_nodeboxes[0],
|
||||
selection_box = { type = "regular" },
|
||||
tiles = {
|
||||
"mcl_cauldrons_cauldron_inner.png^mcl_cauldrons_cauldron_top.png",
|
||||
"mcl_cauldrons_cauldron_inner.png^mcl_cauldrons_cauldron_bottom.png",
|
||||
"mcl_cauldrons_cauldron_side.png"
|
||||
},
|
||||
sounds = mcl_sounds.node_sound_metal_defaults(),
|
||||
_mcl_hardness = 2,
|
||||
_mcl_blast_resistance = 2,
|
||||
|
||||
-- delegated to by mcl_buckets and mcl_potions.
|
||||
on_rightclick = function(place_pos, node, user, itemstack)
|
||||
return mcl_cauldrons.apply_item(place_pos, node, user, itemstack)
|
||||
end,
|
||||
})
|
||||
|
||||
|
||||
--- Water cauldron (1/3) node definition.
|
||||
--
|
||||
-- water cauldron as extension of empty cauldron.
|
||||
-- @name mcl_cauldrons:cauldron_water_1
|
||||
-- @class table
|
||||
mcl_cauldrons.register_cauldron_node("mcl_cauldrons:cauldron_water_1",
|
||||
merge_tables(mcl_cauldrons.registered_cauldrons["mcl_cauldrons:cauldron"], {
|
||||
description = S("Cauldron (1/3 Water)"),
|
||||
groups = {
|
||||
pickaxey = 1,
|
||||
cauldron = 1,
|
||||
cauldron_filled = 1,
|
||||
cauldron_maximum = 3,
|
||||
},
|
||||
node_box = mcl_cauldrons.cauldron_nodeboxes[1],
|
||||
collision_box = mcl_cauldrons.cauldron_nodeboxes[0],
|
||||
tiles = {
|
||||
[1]="(default_water_source_animated.png^[verticalframe:16:0)^mcl_cauldrons_cauldron_top.png",
|
||||
},
|
||||
drop = "mcl_cauldrons:cauldron",
|
||||
_mcl_cauldron_substance = "water",
|
||||
}), "mcl_cauldrons:cauldron")
|
||||
|
||||
--- Water cauldron (2/3) node definition.
|
||||
--
|
||||
-- water cauldron 2/3 as extension of 1/3.
|
||||
-- @name mcl_cauldrons:cauldron_water_2
|
||||
-- @class table
|
||||
mcl_cauldrons.register_cauldron_node("mcl_cauldrons:cauldron_water_2",
|
||||
merge_tables(mcl_cauldrons.registered_cauldrons["mcl_cauldrons:cauldron_water_1"], {
|
||||
description = S("Cauldron (2/3 Water)"),
|
||||
groups = {
|
||||
cauldron_filled = 2,
|
||||
},
|
||||
node_box = mcl_cauldrons.cauldron_nodeboxes[2],
|
||||
}), "mcl_cauldrons:cauldron")
|
||||
|
||||
--- Water cauldron (2/3) node definition.
|
||||
--
|
||||
-- water cauldron 3/3 as extension of 1/3.
|
||||
-- @name mcl_cauldrons:cauldron_water_3
|
||||
-- @class table
|
||||
mcl_cauldrons.register_cauldron_node("mcl_cauldrons:cauldron_water_3",
|
||||
merge_tables(mcl_cauldrons.registered_cauldrons["mcl_cauldrons:cauldron_water_1"], {
|
||||
description = S("Cauldron (3/3 Water)"),
|
||||
groups = {
|
||||
cauldron_filled = 3,
|
||||
},
|
||||
node_box = mcl_cauldrons.cauldron_nodeboxes[3],
|
||||
}), "mcl_cauldrons:cauldron")
|
||||
|
||||
|
||||
-- River Water Cauldron
|
||||
if minetest.get_modpath("mclx_core") then
|
||||
dosubfile("cauldron_river_water.lua")
|
||||
end
|
||||
|
||||
-- Lava Cauldron
|
||||
if minetest.get_modpath("mclx_core") then
|
||||
dosubfile("cauldron_lava.lua")
|
||||
end
|
||||
|
||||
-- Crafting recipe: Cauldron
|
||||
minetest.register_craft({
|
||||
output = "mcl_cauldrons:cauldron",
|
||||
recipe = {
|
||||
{ "mcl_core:iron_ingot", "", "mcl_core:iron_ingot" },
|
||||
{ "mcl_core:iron_ingot", "", "mcl_core:iron_ingot" },
|
||||
{ "mcl_core:iron_ingot", "mcl_core:iron_ingot", "mcl_core:iron_ingot" },
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_abm({
|
||||
label = "cauldrons",
|
||||
nodenames = {"group:cauldron_filled"},
|
||||
interval = 0.5,
|
||||
chance = 1,
|
||||
action = function(pos, node)
|
||||
local EXTINGUISHING_RADIUS = 0.4
|
||||
for _, obj in pairs(minetest.get_objects_inside_radius(pos, EXTINGUISHING_RADIUS)) do
|
||||
if mcl_burning.is_burning(obj) then
|
||||
local newnode = mcl_cauldrons.node_drain_levels(node, 1, "water")
|
||||
if node ~= newnode then
|
||||
-- extinguishing requires 1 level of water from cauldron.
|
||||
minetest.swap_node(pos, newnode)
|
||||
mcl_burning.extinguish(obj)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
})
|
||||
|
||||
|
||||
-- backwards compatibility
|
||||
local aliases = {
|
||||
-- key=old/legacy name; value=current name
|
||||
["mcl_cauldrons:cauldron_1"] = "mcl_cauldrons:cauldron_water_1",
|
||||
["mcl_cauldrons:cauldron_2"] = "mcl_cauldrons:cauldron_water_2",
|
||||
["mcl_cauldrons:cauldron_3"] = "mcl_cauldrons:cauldron_water_3",
|
||||
["mcl_cauldrons:cauldron_1r"] = "mcl_cauldrons:cauldron_river_water_1",
|
||||
["mcl_cauldrons:cauldron_2r"] = "mcl_cauldrons:cauldron_river_water_2",
|
||||
["mcl_cauldrons:cauldron_3r"] = "mcl_cauldrons:cauldron_river_water_3",
|
||||
}
|
||||
for legacy, current in pairs(aliases) do
|
||||
minetest.register_alias(legacy, current)
|
||||
end
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
Unit testing of mcl\_cauldrons using mineunit.
|
||||
|
||||
|
||||
$ luarocks install --server=https://luarocks.org/dev --local mineunit
|
||||
$ luarocks install busted
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
|
||||
-- Add some simple nodes
|
||||
|
||||
local function register_default(name)
|
||||
minetest.register_node(":default:"..name, {
|
||||
description = name.." description",
|
||||
tiles = name.."_texture.png",
|
||||
buildable_to = false,
|
||||
walkable = true,
|
||||
})
|
||||
end
|
||||
|
||||
register_default("furnace")
|
||||
register_default("stone")
|
||||
register_default("stonebrick")
|
||||
register_default("sand")
|
||||
register_default("sandstone")
|
||||
register_default("sandstonebrick")
|
||||
register_default("steelblock")
|
|
@ -0,0 +1,32 @@
|
|||
|
||||
-- Simple digilines mod fixture that logs sent messages, works with some simple digiline mods
|
||||
|
||||
mineunit:set_modpath("digilines", "spec/fixtures")
|
||||
|
||||
_G.digilines = {
|
||||
_msg_log = {},
|
||||
receptor_send = function(pos, rules, channel, msg)
|
||||
table.insert(_G.digilines._msg_log, {
|
||||
pos = pos,
|
||||
rules = rules,
|
||||
channel = channel,
|
||||
msg = msg,
|
||||
})
|
||||
end,
|
||||
rules = {
|
||||
default = {
|
||||
{x=0, y=0, z=-1},
|
||||
{x=1, y=0, z=0},
|
||||
{x=-1, y=0, z=0},
|
||||
{x=0, y=0, z=1},
|
||||
{x=1, y=1, z=0},
|
||||
{x=1, y=-1, z=0},
|
||||
{x=-1, y=1, z=0},
|
||||
{x=-1, y=-1, z=0},
|
||||
{x=0, y=1, z=1},
|
||||
{x=0, y=-1, z=1},
|
||||
{x=0, y=1, z=-1},
|
||||
{x=0, y=-1, z=-1}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
|
||||
-- Simple mesecons fixture that allows many node registrations requiring mesecons
|
||||
|
||||
mineunit:set_modpath("mesecons", "spec/fixtures")
|
||||
mineunit:set_modpath("mesecons_mvps", "spec/fixtures")
|
||||
|
||||
mesecon = {
|
||||
state = {},
|
||||
rules = {
|
||||
default = {
|
||||
{x = 0, y = 0, z = -1},
|
||||
{x = 1, y = 0, z = 0},
|
||||
{x = -1, y = 0, z = 0},
|
||||
{x = 0, y = 0, z = 1},
|
||||
{x = 1, y = 1, z = 0},
|
||||
{x = 1, y = -1, z = 0},
|
||||
{x = -1, y = 1, z = 0},
|
||||
{x = -1, y = -1, z = 0},
|
||||
{x = 0, y = 1, z = 1},
|
||||
{x = 0, y = -1, z = 1},
|
||||
{x = 0, y = 1, z = -1},
|
||||
{x = 0, y = -1, z = -1},
|
||||
}
|
||||
}
|
||||
}
|
||||
mesecon = setmetatable(mesecon, {
|
||||
__call = function(self,...) return self end,
|
||||
__index = function(...) return function(...)end end,
|
||||
})
|
|
@ -0,0 +1 @@
|
|||
active_block_range = 1
|
|
@ -0,0 +1,21 @@
|
|||
|
||||
-- Simple pipeworks fixture with few no-op methods, enough for technic, metatool and jumpdrive
|
||||
|
||||
mineunit:set_modpath("pipeworks", "spec/fixtures")
|
||||
|
||||
local function noop(t)
|
||||
return setmetatable(t, {
|
||||
__call = function(self,...) return self end,
|
||||
__index = function(...) return function(...)end end,
|
||||
})
|
||||
end
|
||||
|
||||
local pipeworks = {
|
||||
button_label = "",
|
||||
fs_helpers = {
|
||||
cycling_button = function(...) return "" end
|
||||
},
|
||||
tptube = {},
|
||||
}
|
||||
pipeworks.tptube = noop(pipeworks.tptube)
|
||||
_G.pipeworks = noop(pipeworks)
|
|
@ -0,0 +1,812 @@
|
|||
#!/usr/bin/env mineunit
|
||||
|
||||
-- unit test for mcl_cauldrons, using mineunit (https://github.com/S-S-X/mineunit)
|
||||
-- quick primer: this runs *outside* of Minetest, with the mineunit executable,
|
||||
-- and calls to actual minetest engine calls must be mocked.
|
||||
require("mineunit")
|
||||
|
||||
mineunit("player")
|
||||
mineunit("protection")
|
||||
mineunit("common/after")
|
||||
mineunit("server")
|
||||
mineunit("voxelmanip")
|
||||
|
||||
fixture("default")
|
||||
fixture("mesecons")
|
||||
fixture("digilines")
|
||||
fixture("pipeworks")
|
||||
|
||||
-- mock mclx_core
|
||||
_get_modpath = minetest.get_modpath
|
||||
minetest.get_modpath = function(modname)
|
||||
if modname == "mclx_core" then return modname end
|
||||
if modname == "doc" then return modname end
|
||||
if modname == "mcl_buckets" then return modname end
|
||||
if modname == "mcl_potions" then return modname end
|
||||
if modname == "mcl_banners" then return modname end
|
||||
return _get_modpath(modname)
|
||||
end
|
||||
|
||||
describe("MineClone2 cauldrons test", function()
|
||||
-- mock liquid sources (mock sound)
|
||||
local s_water_source = "mcl_core:water_source"
|
||||
local s_lava_source = "mcl_core:lava_source"
|
||||
local water_source = {
|
||||
sounds = {
|
||||
place = "place",
|
||||
dig = "dig",
|
||||
}
|
||||
}
|
||||
local lava_source = {
|
||||
paramtype = "light",
|
||||
light_source = minetest.LIGHT_MAX,
|
||||
sounds = {
|
||||
place = "place",
|
||||
dig = "dig",
|
||||
}
|
||||
}
|
||||
minetest.registered_nodes[s_water_source] = water_source
|
||||
minetest.registered_nodes[s_lava_source] = lava_source
|
||||
|
||||
-- Mocked functions and objects.
|
||||
if not minetest.features then
|
||||
minetest.features = {}
|
||||
minetest.features.use_texture_alpha_string_modes = true
|
||||
end
|
||||
if not minetest.get_objects_inside_radius then
|
||||
minetest.get_objects_inside_radius = function(pos, radius) return {} end
|
||||
end
|
||||
|
||||
_G.mcl_sounds = {}
|
||||
_G.mcl_sounds.node_sound_metal_defaults = function(...) end
|
||||
_G.doc = {}
|
||||
_G.doc.add_entry_alias = function(...) end
|
||||
|
||||
-- Create world with 100 x 1 x 3 stone layer and 3 nodes high air layer.
|
||||
world.layout({
|
||||
{{{x=0,y=0,z=-1},{x=99,y=0,z=1}}, "default:stone"},
|
||||
{{{x=0,y=1,z=-1},{x=99,y=3,z=1}}, "air"},
|
||||
-- empty cauldrons at start.
|
||||
{ {x=0, y=1, z=-3}, "mcl_cauldrons:cauldron" },
|
||||
})
|
||||
|
||||
-- Load current mod executing init.lua
|
||||
sourcefile("init")
|
||||
|
||||
-- Execute on mods loaded callbacks to finish loading.
|
||||
mineunit:mods_loaded()
|
||||
|
||||
-- Tell mods that 1 minute passed already to execute possible weird minetest.after hacks.
|
||||
mineunit:execute_globalstep(60)
|
||||
|
||||
local Sam = Player("Sam")
|
||||
|
||||
-- Players join before tests begin
|
||||
setup(function()
|
||||
mineunit:execute_on_joinplayer(Sam)
|
||||
end)
|
||||
|
||||
-- Players leave after tests finished
|
||||
teardown(function()
|
||||
mineunit:execute_on_leaveplayer(Sam)
|
||||
end)
|
||||
|
||||
-- Generate placement test for all registered nodes without not_in_creative_inventory group
|
||||
local function placement_test(name, xpos)
|
||||
return function()
|
||||
Sam:get_inventory():set_stack("main", 1, name)
|
||||
Sam:do_place({x=xpos, y=1, z=0})
|
||||
end
|
||||
end
|
||||
local xpos = 0
|
||||
for nodename, def in pairs(minetest.registered_nodes) do
|
||||
if not (def.groups and def.groups.not_in_creative_inventory) then
|
||||
it("wont crash placing "..nodename, placement_test(nodename, xpos))
|
||||
xpos = xpos + 1
|
||||
end
|
||||
end
|
||||
|
||||
--[[
|
||||
it("placed all nodes", function()
|
||||
pending("This test might be too simple for potentially complex operation and fails if node is changed")
|
||||
local index = 0
|
||||
for nodename, def in pairs(minetest.registered_nodes) do
|
||||
if not (def.groups and def.groups.not_in_creative_inventory) then
|
||||
local node = minetest.get_node({x=index, y=1, z=0})
|
||||
assert.equals(node.name, nodename)
|
||||
index = index + 1
|
||||
end
|
||||
end
|
||||
end)
|
||||
]]
|
||||
|
||||
-- abbreviated symbols
|
||||
local s_cauldron0 = "mcl_cauldrons:cauldron"
|
||||
local s_cauldron1 = "mcl_cauldrons:cauldron_water_1"
|
||||
local s_cauldron2 = "mcl_cauldrons:cauldron_water_2"
|
||||
local s_cauldron3 = "mcl_cauldrons:cauldron_water_3"
|
||||
local s_cauldron1r = "mcl_cauldrons:cauldron_river_water_1"
|
||||
local s_cauldron2r = "mcl_cauldrons:cauldron_river_water_2"
|
||||
local s_cauldron3r = "mcl_cauldrons:cauldron_river_water_3"
|
||||
local s_cauldron1l = "mcl_cauldrons:cauldron_lava_1"
|
||||
local s_cauldron2l = "mcl_cauldrons:cauldron_lava_2"
|
||||
local s_cauldron3l = "mcl_cauldrons:cauldron_lava_3"
|
||||
local s_bucket0 = "mcl_buckets:bucket_empty"
|
||||
local s_bucket1 = "mcl_buckets:bucket_water"
|
||||
local s_bucket1r = "mcl_buckets:bucket_river_water"
|
||||
local s_bucket1l = "mcl_buckets:bucket_lava"
|
||||
local s_bottle0 = "mcl_potions:glass_bottle"
|
||||
local s_bottle1 = "mcl_potions:water"
|
||||
local s_bottle1r = "mcl_potions:river_water"
|
||||
local s_banner0 = "mcl_banners:placeholder_banner"
|
||||
|
||||
it("test state normalizer", function()
|
||||
-- test reducing (substance,fill_level) tuples to a valid cauldron.
|
||||
local result
|
||||
-- synonyms for empty cauldron: (empty,any), (any,0)
|
||||
result = mcl_cauldrons.make_cauldron("empty", 0)
|
||||
assert.equals(s_cauldron0, result)
|
||||
result = mcl_cauldrons.make_cauldron("empty", 1)
|
||||
assert.equals(s_cauldron0, result)
|
||||
result = mcl_cauldrons.make_cauldron("empty", 2)
|
||||
assert.equals(s_cauldron0, result)
|
||||
result = mcl_cauldrons.make_cauldron("empty", 3)
|
||||
assert.equals(s_cauldron0, result)
|
||||
result = mcl_cauldrons.make_cauldron("water", 0)
|
||||
assert.equals(s_cauldron0, result)
|
||||
result = mcl_cauldrons.make_cauldron("water", 1)
|
||||
assert.equals(s_cauldron1, result)
|
||||
result = mcl_cauldrons.make_cauldron("water", 2)
|
||||
assert.equals(s_cauldron2, result)
|
||||
result = mcl_cauldrons.make_cauldron("water", 3)
|
||||
assert.equals(s_cauldron3, result)
|
||||
end)
|
||||
|
||||
it("test state transition rules", function()
|
||||
-- test the rules about filling and emptying cauldrons.
|
||||
local node
|
||||
local newnode
|
||||
local cauldron0 = mcl_cauldrons.registered_cauldrons[s_cauldron0]
|
||||
newnode = mcl_cauldrons.node_fill_levels(cauldron0, 1, "water")
|
||||
assert.equals(s_cauldron1, newnode.name)
|
||||
newnode = mcl_cauldrons.node_fill_levels(cauldron0, 2, "water")
|
||||
assert.equals(s_cauldron2, newnode.name)
|
||||
newnode = mcl_cauldrons.node_fill_levels(cauldron0, 3, "water")
|
||||
assert.equals(s_cauldron3, newnode.name)
|
||||
|
||||
local cauldron1 = mcl_cauldrons.registered_cauldrons[s_cauldron1]
|
||||
assert.is.truthy(mcl_cauldrons.node_has_substance(cauldron1, "water"))
|
||||
assert.equals(1, mcl_cauldrons.node_get_level(cauldron1))
|
||||
newnode = mcl_cauldrons.node_fill_levels(cauldron1, 1, "water")
|
||||
assert.equals(s_cauldron2, newnode.name)
|
||||
newnode = mcl_cauldrons.node_fill_levels(cauldron1, 2, "water")
|
||||
assert.equals(s_cauldron3, newnode.name)
|
||||
|
||||
local cauldron2 = mcl_cauldrons.registered_cauldrons[s_cauldron2]
|
||||
newnode = mcl_cauldrons.node_fill_levels(cauldron2, 1, "water")
|
||||
assert.equals(s_cauldron3, newnode.name)
|
||||
newnode = mcl_cauldrons.node_fill_levels(cauldron2, 2, "water")
|
||||
assert.equals(s_cauldron3, newnode.name)
|
||||
newnode = mcl_cauldrons.node_drain_levels(cauldron2, 1, "water")
|
||||
assert.equals(s_cauldron1, newnode.name)
|
||||
newnode = mcl_cauldrons.node_drain_levels(cauldron2, 2, "water")
|
||||
assert.equals(s_cauldron0, newnode.name)
|
||||
|
||||
local cauldron3 = mcl_cauldrons.registered_cauldrons[s_cauldron3]
|
||||
newnode = mcl_cauldrons.node_drain_levels(cauldron3, 1, "water")
|
||||
assert.equals(s_cauldron2, newnode.name)
|
||||
newnode = mcl_cauldrons.node_drain_levels(cauldron3, 2, "water")
|
||||
assert.equals(s_cauldron1, newnode.name)
|
||||
newnode = mcl_cauldrons.node_drain_levels(cauldron3, 3, "water")
|
||||
assert.equals(s_cauldron0, newnode.name)
|
||||
newnode = mcl_cauldrons.node_drain_levels(cauldron3, 4, "water")
|
||||
assert.equals(nil, newnode)
|
||||
end)
|
||||
|
||||
|
||||
----
|
||||
-- helper functions
|
||||
|
||||
-- all cauldron activity at this position.
|
||||
local CAULDRON_POS = { x=0, y=1, z=-3 }
|
||||
|
||||
-- Make sure node (at CAULDRON_POS) is a particular cauldron.
|
||||
local function force_cauldron(nodename)
|
||||
local node = { name=nodename }
|
||||
minetest.set_node(CAULDRON_POS, node)
|
||||
return minetest.get_node(CAULDRON_POS)
|
||||
end
|
||||
|
||||
local function assert_cauldron(nodename)
|
||||
local node = minetest.get_node(CAULDRON_POS)
|
||||
assert.is_not_nil(node)
|
||||
assert.equals(nodename, node.name)
|
||||
return node
|
||||
end
|
||||
|
||||
-- Make sure Sam has, and is wielding, inventory.
|
||||
local function force_inv(itemname)
|
||||
Sam:get_inventory():set_stack("main", 1, itemname)
|
||||
local itemstack = Sam:get_inventory():get_stack("main", 1)
|
||||
return itemstack
|
||||
end
|
||||
|
||||
local function assert_inv(itemname)
|
||||
itemstack = Sam:get_inventory():get_stack("main", 1)
|
||||
assert.equals(itemname, itemstack:get_name())
|
||||
return itemstack
|
||||
end
|
||||
|
||||
-- mimick right-clicking (placing) item onto cauldron at CAULDRON_POS.
|
||||
local function rclick_cauldron()
|
||||
local node = minetest.get_node(CAULDRON_POS)
|
||||
local nodedef = minetest.registered_nodes[node.name]
|
||||
local itemstack = Sam:get_inventory():get_stack("main", 1)
|
||||
-- do_place() not viable as buckets/potions/etc. (and their on_place()) are not loaded in this unit test.
|
||||
local newstack = nodedef.on_rightclick(CAULDRON_POS, node, Sam, itemstack)
|
||||
Sam:get_inventory():set_stack("main", 1, newstack)
|
||||
return newstack
|
||||
end
|
||||
|
||||
|
||||
-- mock buckets
|
||||
local bucket0 = {
|
||||
description="Bucket",
|
||||
groups = { bucket=1 },
|
||||
}
|
||||
local bucket1 = {
|
||||
description="Water Bucket",
|
||||
groups = { bucket=1 },
|
||||
}
|
||||
local bucket1r = {
|
||||
description="River Water Bucket",
|
||||
groups = { bucket=1 },
|
||||
}
|
||||
local bucket1l = {
|
||||
description="Lava Bucket",
|
||||
groups = { bucket=1 },
|
||||
}
|
||||
minetest.registered_items[s_bucket0] = bucket0
|
||||
minetest.registered_items[s_bucket1] = bucket1
|
||||
minetest.registered_items[s_bucket1r] = bucket1r
|
||||
|
||||
describe("apply empty bucket to cauldron", function()
|
||||
----
|
||||
-- test the implementation details (in the spirit of TDD)
|
||||
it(", implementation details", function()
|
||||
|
||||
-- empty + full water cauldron = empty cauldron, water bucket
|
||||
local itemstack0 = ItemStack(s_bucket0)
|
||||
|
||||
local pos = CAULDRON_POS
|
||||
local node = { name=s_cauldron3 }
|
||||
local newnode, newitemstack = mcl_cauldrons.BucketProxy:apply_basic_rules(itemstack0, node)
|
||||
assert.is_not_nil(newnode)
|
||||
assert.is_not_nil(newitemstack)
|
||||
assert.equals(s_cauldron0, newnode.name)
|
||||
assert.equals(s_bucket1, newitemstack:get_name())
|
||||
|
||||
-- empty bucket + 2/3 water cauldron = nil, nil (no change)
|
||||
local node = { name=s_cauldron2 }
|
||||
newnode, newitemstack = mcl_cauldrons.BucketProxy:apply_basic_rules(itemstack0, node)
|
||||
assert.is_nil(newnode)
|
||||
assert.is_nil(newitemstack)
|
||||
|
||||
-- empty bucket + 1/3 water cauldron = nil, nil (no change)
|
||||
local node = { name=s_cauldron1 }
|
||||
newnode, newitemstack = mcl_cauldrons.BucketProxy:apply_basic_rules(itemstack0, node)
|
||||
assert.is_nil(newnode)
|
||||
assert.is_nil(newitemstack)
|
||||
|
||||
-- empty bucket + empty cauldron = nil, nil (no change)
|
||||
local node = { name=s_cauldron0 }
|
||||
newnode, newitemstack = mcl_cauldrons.BucketProxy:apply_basic_rules(itemstack0, node)
|
||||
assert.is_nil(newnode)
|
||||
assert.is_nil(newitemstack)
|
||||
|
||||
-- empty bucket + lava cauldron = empty cauldron, lava bucket
|
||||
local node = { name=s_cauldron3l }
|
||||
newnode, newitemstack = mcl_cauldrons.BucketProxy:apply_basic_rules(itemstack0, node)
|
||||
assert.is_not_nil(newnode)
|
||||
assert.is_not_nil(newitemstack)
|
||||
assert.equals(s_cauldron0, newnode.name)
|
||||
assert.equals(s_bucket1l, newitemstack:get_name())
|
||||
end)
|
||||
|
||||
|
||||
----
|
||||
-- mimick world activity (validate for gameplay)
|
||||
it(", mimick world activity", function()
|
||||
|
||||
force_cauldron(s_cauldron3)
|
||||
local node = assert_cauldron(s_cauldron3)
|
||||
assert.equals(3, mcl_cauldrons.node_get_level(node))
|
||||
-- start with empty bucket.
|
||||
force_inv(s_bucket0)
|
||||
local itemstack = assert_inv(s_bucket0)
|
||||
assert.equals("mcl_buckets:bucket_empty", itemstack:get_name())
|
||||
|
||||
-- apply itemstack (rightclick empty bucket) to cauldron (full water) -> empty cauldron, water bucket.
|
||||
local newstack = rclick_cauldron()
|
||||
assert.not_equals(nil, newstack)
|
||||
assert.equals("mcl_buckets:bucket_water", newstack:get_name())
|
||||
assert_inv(s_bucket1)
|
||||
-- check cauldron node updated properly.
|
||||
assert_cauldron(s_cauldron0)
|
||||
|
||||
-- apply empty bucket to 2/3 cauldron -> (no change)
|
||||
force_cauldron(s_cauldron2)
|
||||
force_inv(s_bucket0)
|
||||
rclick_cauldron()
|
||||
assert_cauldron(s_cauldron2)
|
||||
assert_inv(s_bucket0)
|
||||
|
||||
-- apply empty bucket to 1/3 cauldron -> (no change)
|
||||
force_cauldron(s_cauldron1)
|
||||
force_inv(s_bucket0)
|
||||
rclick_cauldron()
|
||||
assert_cauldron(s_cauldron1)
|
||||
assert_inv(s_bucket0)
|
||||
|
||||
-- apply empty bucket to empty cauldron -> (no change)
|
||||
force_cauldron(s_cauldron0)
|
||||
force_inv(s_bucket0)
|
||||
rclick_cauldron()
|
||||
assert_cauldron(s_cauldron0)
|
||||
assert_inv(s_bucket0)
|
||||
|
||||
|
||||
-- apply empty bucket to full river water cauldron -> empty cauldron, river water bucket
|
||||
force_cauldron(s_cauldron3r)
|
||||
force_inv(s_bucket0)
|
||||
rclick_cauldron()
|
||||
assert_cauldron(s_cauldron0)
|
||||
assert_inv(s_bucket1r)
|
||||
|
||||
-- apply empty bucket to 2/3 river water cauldron -> empty cauldron, river water bucket
|
||||
force_cauldron(s_cauldron2r)
|
||||
force_inv(s_bucket0)
|
||||
rclick_cauldron()
|
||||
assert_cauldron(s_cauldron2r)
|
||||
assert_inv(s_bucket0)
|
||||
|
||||
-- apply empty bucket to 1/3 river water cauldron -> empty cauldron, river water bucket
|
||||
force_cauldron(s_cauldron1r)
|
||||
force_inv(s_bucket0)
|
||||
rclick_cauldron()
|
||||
assert_cauldron(s_cauldron1r)
|
||||
assert_inv(s_bucket0)
|
||||
|
||||
|
||||
-- apply empty bucket to full lava cauldron -> empty cauldron, lava bucket
|
||||
force_cauldron(s_cauldron3l)
|
||||
force_inv(s_bucket0)
|
||||
rclick_cauldron()
|
||||
assert_cauldron(s_cauldron0)
|
||||
assert_inv(s_bucket1l)
|
||||
|
||||
-- apply empty bucket to 2/3 lava cauldron -> empty cauldron, lava bucket
|
||||
force_cauldron(s_cauldron2l)
|
||||
force_inv(s_bucket0)
|
||||
rclick_cauldron()
|
||||
assert_cauldron(s_cauldron2l)
|
||||
assert_inv(s_bucket0)
|
||||
|
||||
-- apply empty bucket to 1/3 lava cauldron -> empty cauldron, lava bucket
|
||||
force_cauldron(s_cauldron1l)
|
||||
force_inv(s_bucket0)
|
||||
rclick_cauldron()
|
||||
assert_cauldron(s_cauldron1l)
|
||||
assert_inv(s_bucket0)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("apply water bucket to cauldron", function()
|
||||
----
|
||||
-- test the implementation details (gets messy).
|
||||
it(", implementation details", function()
|
||||
local itemstack0 = ItemStack(s_bucket1)
|
||||
|
||||
-- water bucket + empty cauldrons = full water cauldron, empty bucket
|
||||
local pos = CAULDRON_POS
|
||||
local node = { name=s_cauldron0 }
|
||||
|
||||
local newnode, newitemstack = mcl_cauldrons.BucketProxy:apply_basic_rules(itemstack0, node)
|
||||
assert.is_not_nil(newnode)
|
||||
assert.is_not_nil(newitemstack)
|
||||
assert.equals(s_cauldron3, newnode.name)
|
||||
assert.equals(s_bucket0, newitemstack:get_name())
|
||||
|
||||
-- water bucket + 1/3 cauldron = full water cauldron, empty bucket
|
||||
node = { name=s_cauldron1 }
|
||||
local newnode, newitemstack = mcl_cauldrons.BucketProxy:apply_basic_rules(itemstack0, node)
|
||||
assert.equals(s_cauldron3, newnode.name)
|
||||
assert.equals(s_bucket0, newitemstack:get_name())
|
||||
|
||||
-- water bucket + 2/3 cauldron = full water cauldron, empty bucket
|
||||
node = { name=s_cauldron2 }
|
||||
local newnode, newitemstack = mcl_cauldrons.BucketProxy:apply_basic_rules(itemstack0, node)
|
||||
assert.equals(s_cauldron3, newnode.name)
|
||||
assert.equals(s_bucket0, newitemstack:get_name())
|
||||
|
||||
-- water bucket + full cauldron = full water cauldron, empty bucket (wastes the water bucket)
|
||||
node = { name=s_cauldron3 }
|
||||
local newnode, newitemstack = mcl_cauldrons.BucketProxy:apply_basic_rules(itemstack0, node)
|
||||
assert.equals(s_cauldron3, newnode.name)
|
||||
assert.equals(s_bucket0, newitemstack:get_name())
|
||||
end)
|
||||
|
||||
----
|
||||
-- mimick world activity (validate for gameplay)
|
||||
|
||||
it(", mimick world activity", function()
|
||||
-- apply water bucket to full cauldron -> cauldron_water_3, empty bucket (bucket wasted)
|
||||
force_cauldron(s_cauldron3)
|
||||
force_inv(s_bucket1)
|
||||
rclick_cauldron()
|
||||
assert_cauldron(s_cauldron3)
|
||||
assert_inv(s_bucket0)
|
||||
|
||||
-- apply water bucket to 2/3 cauldron -> cauldron_water_3, empty bucket
|
||||
force_cauldron(s_cauldron2)
|
||||
force_inv(s_bucket1)
|
||||
rclick_cauldron()
|
||||
assert_cauldron(s_cauldron3)
|
||||
assert_inv(s_bucket0)
|
||||
|
||||
-- apply water bucket to 1/3 cauldron -> cauldron_water_3, empty bucket
|
||||
force_cauldron(s_cauldron1)
|
||||
force_inv(s_bucket1)
|
||||
rclick_cauldron()
|
||||
assert_cauldron(s_cauldron3)
|
||||
assert_inv(s_bucket0)
|
||||
|
||||
-- apply water bucket to empty cauldron -> cauldron_water_3, empty bucket
|
||||
force_cauldron(s_cauldron0)
|
||||
force_inv(s_bucket1)
|
||||
rclick_cauldron()
|
||||
assert_cauldron(s_cauldron3)
|
||||
assert_inv(s_bucket0)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("apply river water bucket to cauldron #riverwaterbucket", function()
|
||||
it(", implementation details", function()
|
||||
assert.is_not_nil(minetest.registered_nodes["mcl_cauldrons:cauldron_river_water_1"])
|
||||
assert.is_not_nil(minetest.registered_nodes["mcl_cauldrons:cauldron_river_water_2"])
|
||||
assert.is_not_nil(minetest.registered_nodes["mcl_cauldrons:cauldron_river_water_3"])
|
||||
----
|
||||
-- test the implementation details (gets messy).
|
||||
local itemstack0 = ItemStack(s_bucket1r)
|
||||
|
||||
-- river water bucket + empty cauldrons = full river water cauldron, empty bucket
|
||||
local pos = CAULDRON_POS
|
||||
local node = { name=s_cauldron0 }
|
||||
|
||||
local newnode, newitemstack = mcl_cauldrons.BucketProxy:apply_basic_rules(itemstack0, node)
|
||||
assert.is_not_nil(newnode)
|
||||
assert.is_not_nil(newitemstack)
|
||||
assert.equals(s_cauldron3r, newnode.name)
|
||||
assert.equals(s_bucket0, newitemstack:get_name())
|
||||
|
||||
-- river water bucket + 1/3 cauldron = full river water cauldron, empty bucket
|
||||
node = { name=s_cauldron1r }
|
||||
local newnode, newitemstack = mcl_cauldrons.BucketProxy:apply_basic_rules(itemstack0, node)
|
||||
assert.equals(s_cauldron3r, newnode.name)
|
||||
assert.equals(s_bucket0, newitemstack:get_name())
|
||||
|
||||
-- river water bucket + 2/3 cauldron = full river water cauldron, empty bucket
|
||||
node = { name=s_cauldron2r }
|
||||
local newnode, newitemstack = mcl_cauldrons.BucketProxy:apply_basic_rules(itemstack0, node)
|
||||
assert.equals(s_cauldron3r, newnode.name)
|
||||
assert.equals(s_bucket0, newitemstack:get_name())
|
||||
|
||||
-- river water bucket + full cauldron = full river water cauldron, empty bucket (wastes the river water bucket)
|
||||
node = { name=s_cauldron3r }
|
||||
local newnode, newitemstack = mcl_cauldrons.BucketProxy:apply_basic_rules(itemstack0, node)
|
||||
assert.equals(s_cauldron3r, newnode.name)
|
||||
assert.equals(s_bucket0, newitemstack:get_name())
|
||||
end)
|
||||
|
||||
----
|
||||
-- mimick world activity (validate for gameplay)
|
||||
|
||||
it(", mimick world activity", function()
|
||||
-- apply river water bucket to full cauldron -> cauldron_water_3, empty bucket (bucket wasted)
|
||||
force_cauldron(s_cauldron3r)
|
||||
force_inv(s_bucket1r)
|
||||
rclick_cauldron()
|
||||
assert_cauldron(s_cauldron3r)
|
||||
assert_inv(s_bucket0)
|
||||
|
||||
-- apply river water bucket to 2/3 cauldron -> cauldron_water_3, empty bucket
|
||||
force_cauldron(s_cauldron2r)
|
||||
force_inv(s_bucket1r)
|
||||
rclick_cauldron()
|
||||
assert_cauldron(s_cauldron3r)
|
||||
assert_inv(s_bucket0)
|
||||
|
||||
-- apply river water bucket to 1/3 cauldron -> cauldron_water_3, empty bucket
|
||||
force_cauldron(s_cauldron1r)
|
||||
force_inv(s_bucket1r)
|
||||
rclick_cauldron()
|
||||
assert_cauldron(s_cauldron3r)
|
||||
assert_inv(s_bucket0)
|
||||
|
||||
-- apply river water bucket to empty cauldron -> cauldron_water_3, empty bucket
|
||||
force_cauldron(s_cauldron0)
|
||||
force_inv(s_bucket1r)
|
||||
rclick_cauldron()
|
||||
assert_cauldron(s_cauldron3r)
|
||||
assert_inv(s_bucket0)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("apply lava bucket to cauldron #lavabucket", function()
|
||||
it(", implementation details", function()
|
||||
assert.is_not_nil(minetest.registered_nodes["mcl_cauldrons:cauldron_lava_1"])
|
||||
assert.is_not_nil(minetest.registered_nodes["mcl_cauldrons:cauldron_lava_2"])
|
||||
assert.is_not_nil(minetest.registered_nodes["mcl_cauldrons:cauldron_lava_3"])
|
||||
----
|
||||
-- test the implementation details (gets messy).
|
||||
local itemstack0 = ItemStack(s_bucket1l)
|
||||
|
||||
-- lava bucket + empty cauldrons = full lava cauldron, empty bucket
|
||||
local pos = CAULDRON_POS
|
||||
local node = { name=s_cauldron0 }
|
||||
|
||||
local newnode, newitemstack = mcl_cauldrons.BucketProxy:apply_basic_rules(itemstack0, node)
|
||||
assert.is_not_nil(newnode)
|
||||
assert.is_not_nil(newitemstack)
|
||||
assert.equals(s_cauldron3l, newnode.name)
|
||||
assert.equals(s_bucket0, newitemstack:get_name())
|
||||
|
||||
-- lava bucket + 1/3 cauldron = full lava cauldron, empty bucket
|
||||
node = { name=s_cauldron1l }
|
||||
local newnode, newitemstack = mcl_cauldrons.BucketProxy:apply_basic_rules(itemstack0, node)
|
||||
assert.equals(s_cauldron3l, newnode.name)
|
||||
assert.equals(s_bucket0, newitemstack:get_name())
|
||||
|
||||
-- lava bucket + 2/3 cauldron = full lava cauldron, empty bucket
|
||||
node = { name=s_cauldron2l }
|
||||
local newnode, newitemstack = mcl_cauldrons.BucketProxy:apply_basic_rules(itemstack0, node)
|
||||
assert.equals(s_cauldron3l, newnode.name)
|
||||
assert.equals(s_bucket0, newitemstack:get_name())
|
||||
|
||||
-- lava bucket + full cauldron = full lava cauldron, empty bucket (wastes the lava bucket)
|
||||
node = { name=s_cauldron3l }
|
||||
local newnode, newitemstack = mcl_cauldrons.BucketProxy:apply_basic_rules(itemstack0, node)
|
||||
assert.equals(s_cauldron3l, newnode.name)
|
||||
assert.equals(s_bucket0, newitemstack:get_name())
|
||||
end)
|
||||
|
||||
----
|
||||
-- mimick world activity (validate for gameplay)
|
||||
|
||||
it(", mimick world activity", function()
|
||||
-- apply lava bucket to full cauldron -> cauldron_water_3, empty bucket (bucket wasted)
|
||||
force_cauldron(s_cauldron3l)
|
||||
force_inv(s_bucket1l)
|
||||
rclick_cauldron()
|
||||
assert_cauldron(s_cauldron3l)
|
||||
assert_inv(s_bucket0)
|
||||
|
||||
-- apply lava bucket to 2/3 cauldron -> cauldron_water_3, empty bucket
|
||||
force_cauldron(s_cauldron2l)
|
||||
force_inv(s_bucket1l)
|
||||
rclick_cauldron()
|
||||
assert_cauldron(s_cauldron3l)
|
||||
assert_inv(s_bucket0)
|
||||
|
||||
-- apply lava bucket to 1/3 cauldron -> cauldron_water_3, empty bucket
|
||||
force_cauldron(s_cauldron1l)
|
||||
force_inv(s_bucket1l)
|
||||
rclick_cauldron()
|
||||
assert_cauldron(s_cauldron3l)
|
||||
assert_inv(s_bucket0)
|
||||
|
||||
-- apply lava bucket to empty cauldron -> cauldron_water_3, empty bucket
|
||||
force_cauldron(s_cauldron0)
|
||||
force_inv(s_bucket1l)
|
||||
rclick_cauldron()
|
||||
assert_cauldron(s_cauldron3l)
|
||||
assert_inv(s_bucket0)
|
||||
end)
|
||||
end)
|
||||
|
||||
|
||||
-- mock potions
|
||||
local bottle0 = {
|
||||
description="Glass Bottle",
|
||||
groups = { potion=1 },
|
||||
}
|
||||
local bottle1 = {
|
||||
description="Water Bottle",
|
||||
groups = { potion=1 },
|
||||
}
|
||||
local bottle1r = {
|
||||
description="River Water Bottle",
|
||||
groups = { potion=1 },
|
||||
}
|
||||
minetest.registered_items[s_bottle0] = bottle0
|
||||
minetest.registered_items[s_bottle1] = bottle1
|
||||
minetest.registered_items[s_bottle1r] = bottle1r
|
||||
|
||||
describe("apply glass/empty bottle to cauldron", function()
|
||||
----
|
||||
-- implementation details
|
||||
|
||||
it(", implementation details", function()
|
||||
-- empty bottle + full cauldron = cauldron_water_2, water bottle
|
||||
local itemstack0 = ItemStack(s_bottle0)
|
||||
local pos = CAULDRON_POS
|
||||
local node = { name=s_cauldron3 }
|
||||
-- force to full cauldron
|
||||
minetest.set_node(pos, node)
|
||||
|
||||
local newnode, newitemstack = mcl_cauldrons.BottleProxy:apply_basic_rules(itemstack0, node)
|
||||
assert.is_not_nil(newnode)
|
||||
assert.equals(s_cauldron2, newnode.name)
|
||||
assert.equals(s_bottle1, newitemstack:get_name())
|
||||
|
||||
-- empty bottle + 2/3 water cauldron = cauldron_water_1, water_bottle
|
||||
node = { name=s_cauldron2 }
|
||||
local newnode, newitemstack = mcl_cauldrons.BottleProxy:apply_basic_rules(itemstack0, node)
|
||||
assert.is_not_nil(newnode)
|
||||
assert.equals("mcl_cauldrons:cauldron_water_1", newnode.name)
|
||||
assert.equals("mcl_potions:water", newitemstack:get_name())
|
||||
|
||||
-- empty bottle + 1/3 water cauldron = empty cauldron, water_bottle
|
||||
node = { name=s_cauldron1 }
|
||||
local newnode, newitemstack = mcl_cauldrons.BottleProxy:apply_basic_rules(itemstack0, node)
|
||||
assert.equals("mcl_cauldrons:cauldron", newnode.name)
|
||||
assert.equals("mcl_potions:water", newitemstack:get_name())
|
||||
|
||||
-- empty bottle + empty cauldron = nil, nil (no changes)
|
||||
node = { name=s_cauldron0 }
|
||||
local newnode, newitemstack = mcl_cauldrons.BottleProxy:apply_basic_rules(itemstack0, node)
|
||||
assert.equals(nil, newnode)
|
||||
assert.equals(nil, newitemstack)
|
||||
end)
|
||||
|
||||
----
|
||||
-- mimick world activity (validate for gameplay)
|
||||
it(", mimick world activity", function()
|
||||
|
||||
-- apply empty bottle to empty cauldron -> (no change)
|
||||
force_cauldron(s_cauldron0)
|
||||
force_inv(s_bottle0)
|
||||
rclick_cauldron()
|
||||
assert_cauldron(s_cauldron0)
|
||||
assert_inv(s_bottle0)
|
||||
|
||||
-- apply empty bottle to 1/3 cauldron -> empty cauldron, water bottle.
|
||||
force_cauldron(s_cauldron1)
|
||||
force_inv(s_bottle0)
|
||||
rclick_cauldron()
|
||||
assert_cauldron(s_cauldron0)
|
||||
assert_inv(s_bottle1)
|
||||
|
||||
-- apply empty bottle to 2/3 cauldron -> cauldron_water_1, water_bottle.
|
||||
force_cauldron(s_cauldron2)
|
||||
force_inv(s_bottle0)
|
||||
rclick_cauldron()
|
||||
assert_cauldron(s_cauldron1)
|
||||
assert_inv(s_bottle1)
|
||||
|
||||
-- apply empty bottle to full cauldron -> cauldron_water_2, water_bottle.
|
||||
force_cauldron(s_cauldron3)
|
||||
force_inv(s_bottle0)
|
||||
rclick_cauldron()
|
||||
assert_cauldron(s_cauldron2)
|
||||
assert_inv(s_bottle1)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("apply water bottle to cauldron", function()
|
||||
it("water battle vs cauldron implementation details", function()
|
||||
----
|
||||
-- implementation details
|
||||
|
||||
local itemstack0 = ItemStack(s_bottle1)
|
||||
local pos = CAULDRON_POS
|
||||
local node = { name=s_cauldron0 }
|
||||
-- force to empty cauldron
|
||||
minetest.set_node(pos, node)
|
||||
|
||||
-- water bottle + empty cauldron = cauldron_water_1, empty bottle
|
||||
local newnode, newitemstack = mcl_cauldrons.BottleProxy:apply_basic_rules(itemstack0, node)
|
||||
assert.is_not_nil(newnode)
|
||||
assert.equals(s_cauldron1, newnode.name)
|
||||
assert.equals(s_bottle0, newitemstack:get_name())
|
||||
|
||||
-- water bottle + 1/3 water cauldron = cauldron_water_2, empty bottle
|
||||
node = { name=s_cauldron1 }
|
||||
local newnode, newitemstack = mcl_cauldrons.BottleProxy:apply_basic_rules(itemstack0, node)
|
||||
assert.equals(s_cauldron2, newnode.name)
|
||||
assert.equals(s_bottle0, newitemstack:get_name())
|
||||
|
||||
-- water bottle + 2/3 water cauldron = cauldron_water_3, empty bottle
|
||||
node = { name=s_cauldron2 }
|
||||
local newnode, newitemstack = mcl_cauldrons.BottleProxy:apply_basic_rules(itemstack0, node)
|
||||
assert.equals(s_cauldron3, newnode.name)
|
||||
assert.equals(s_bottle0, newitemstack:get_name())
|
||||
|
||||
-- water bottle + full water cauldron = nil, nil (no change)
|
||||
node = { name=s_cauldron3 }
|
||||
local newnode, newitemstack = mcl_cauldrons.BottleProxy:apply_basic_rules(itemstack0, node)
|
||||
assert.equals(nil, newnode)
|
||||
assert.equals(nil, newitemstack)
|
||||
end)
|
||||
|
||||
----
|
||||
-- mimick world activity (validate for gameplay)
|
||||
|
||||
it("water bottle vs cauldron, mimick world activity", function()
|
||||
-- apply water bottle to empty cauldron -> cauldron1, empty bottle
|
||||
force_cauldron(s_cauldron0)
|
||||
force_inv(s_bottle1)
|
||||
rclick_cauldron()
|
||||
assert_cauldron(s_cauldron1)
|
||||
assert_inv(s_bottle0)
|
||||
|
||||
-- apply water bottle to 1/3 cauldron -> cauldron2, empty bottle
|
||||
force_cauldron(s_cauldron1)
|
||||
force_inv(s_bottle1)
|
||||
rclick_cauldron()
|
||||
assert_cauldron(s_cauldron2)
|
||||
assert_inv(s_bottle0)
|
||||
|
||||
-- apply water bottle to 2/3 cauldron -> cauldron3, empty bottle
|
||||
force_cauldron(s_cauldron2)
|
||||
force_inv(s_bottle1)
|
||||
rclick_cauldron()
|
||||
assert_cauldron(s_cauldron3)
|
||||
assert_inv(s_bottle0)
|
||||
|
||||
-- apply water bottle to full cauldron -> (no change)
|
||||
force_cauldron(s_cauldron3)
|
||||
force_inv(s_bottle1)
|
||||
rclick_cauldron()
|
||||
assert_cauldron(s_cauldron3)
|
||||
assert_inv(s_bottle1)
|
||||
end)
|
||||
end)
|
||||
|
||||
-- mock banner
|
||||
local banner0 = {
|
||||
description="Placeholder Banner",
|
||||
groups = { banner=1 },
|
||||
}
|
||||
minetest.registered_items[s_banner0] = banner0
|
||||
|
||||
describe("apply banner to cauldron", function()
|
||||
it(", implementation details", function()
|
||||
local itemstack0 = ItemStack(s_banner0)
|
||||
local node = { name=s_cauldron3 }
|
||||
local newnode, newitem = mcl_cauldrons.BannerProxy:apply_basic_rules(itemstack0, node)
|
||||
assert.is_not_nil(newnode)
|
||||
assert.is_not_nil(newitem)
|
||||
end)
|
||||
|
||||
it(", mimick world activity", function()
|
||||
force_cauldron(s_cauldron3)
|
||||
assert_cauldron(s_cauldron3)
|
||||
force_inv(s_banner0)
|
||||
assert_inv(s_banner0)
|
||||
rclick_cauldron()
|
||||
assert_cauldron(s_cauldron2)
|
||||
assert_inv(s_banner0)
|
||||
end)
|
||||
end)
|
||||
|
||||
|
||||
-- Execute globalstep few times just to see if something happens
|
||||
it("gloabalstep works", function()
|
||||
for _=1,60 do
|
||||
mineunit:execute_globalstep(0.42)
|
||||
end
|
||||
end)
|
||||
|
||||
end)
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
time_step = 100
|
||||
verbose = 3
|
||||
exclude = {
|
||||
"integration_test",
|
||||
}
|
|
@ -773,8 +773,7 @@ end
|
|||
|
||||
local grass_spread_randomizer = PseudoRandom(minetest.get_mapgen_setting("seed"))
|
||||
|
||||
-- Return appropriate grass block node for pos
|
||||
function mcl_core.get_grass_block_type(pos)
|
||||
function mcl_core.get_grass_palette_index(pos)
|
||||
local biome_data = minetest.get_biome_data(pos)
|
||||
local index = 0
|
||||
if biome_data then
|
||||
|
@ -785,7 +784,12 @@ function mcl_core.get_grass_block_type(pos)
|
|||
index = reg_biome._mcl_palette_index
|
||||
end
|
||||
end
|
||||
return {name="mcl_core:dirt_with_grass", param2=index}
|
||||
return index
|
||||
end
|
||||
|
||||
-- Return appropriate grass block node for pos
|
||||
function mcl_core.get_grass_block_type(pos)
|
||||
return {name = "mcl_core:dirt_with_grass", param2 = mcl_core.get_grass_palette_index(pos)}
|
||||
end
|
||||
|
||||
------------------------------
|
||||
|
|
|
@ -365,7 +365,7 @@ minetest.register_node("mcl_core:dirt_with_grass", {
|
|||
overlay_tiles = {"mcl_core_grass_block_top.png", "", {name="mcl_core_grass_block_side_overlay.png", tileable_vertical=false}},
|
||||
palette = "mcl_core_palette_grass.png",
|
||||
palette_index = 0,
|
||||
color = "#55aa60",
|
||||
color = "#8EB971",
|
||||
is_ground_content = true,
|
||||
stack_max = 64,
|
||||
groups = {handy=1,shovely=1,dirt=2,grass_block=1, grass_block_no_snow=1, soil=1, soil_sapling=2, soil_sugarcane=1, cultivatable=2, spreading_dirt_type=1, enderman_takable=1, building_block=1},
|
||||
|
|
|
@ -53,7 +53,10 @@ minetest.register_node("mcl_core:reeds", {
|
|||
_doc_items_longdesc = S("Sugar canes are a plant which has some uses in crafting. Sugar canes will slowly grow up to 3 blocks when they are next to water and are placed on a grass block, dirt, sand, red sand, podzol or coarse dirt. When a sugar cane is broken, all sugar canes connected above will break as well."),
|
||||
_doc_items_usagehelp = S("Sugar canes can only be placed top of other sugar canes and on top of blocks on which they would grow."),
|
||||
drawtype = "plantlike",
|
||||
paramtype2 = "color",
|
||||
tiles = {"default_papyrus.png"},
|
||||
palette = "mcl_core_palette_grass.png",
|
||||
palette_index = 0,
|
||||
inventory_image = "mcl_core_reeds.png",
|
||||
wield_image = "mcl_core_reeds.png",
|
||||
paramtype = "light",
|
||||
|
@ -79,6 +82,7 @@ minetest.register_node("mcl_core:reeds", {
|
|||
groups = {dig_immediate=3, craftitem=1, deco_block=1, plant=1, non_mycelium_plant=1, dig_by_piston=1},
|
||||
sounds = mcl_sounds.node_sound_leaves_defaults(),
|
||||
node_placement_prediction = "",
|
||||
drop = "mcl_core:reeds", -- to prevent color inheritation
|
||||
on_place = mcl_util.generate_on_place_plant_function(function(place_pos, place_node)
|
||||
local soil_pos = {x=place_pos.x, y=place_pos.y-1, z=place_pos.z}
|
||||
local soil_node = minetest.get_node_or_nil(soil_pos)
|
||||
|
@ -114,6 +118,15 @@ minetest.register_node("mcl_core:reeds", {
|
|||
return false
|
||||
|
||||
end),
|
||||
on_construct = function(pos)
|
||||
local node = minetest.get_node(pos)
|
||||
if node.param2 == 0 then
|
||||
node.param2 = mcl_core.get_grass_palette_index(pos)
|
||||
if node.param2 ~= 0 then
|
||||
minetest.set_node(pos, node)
|
||||
end
|
||||
end
|
||||
end,
|
||||
_mcl_blast_resistance = 0,
|
||||
_mcl_hardness = 0,
|
||||
})
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 277 B After Width: | Height: | Size: 1.9 KiB |
|
@ -0,0 +1,14 @@
|
|||
# mcl_dye
|
||||
|
||||
# Bone meal API
|
||||
Callback and particle functions.
|
||||
|
||||
## mcl_dye.add_bone_meal_particle(pos, def)
|
||||
Spawns standard or custom bone meal particles.
|
||||
* `pos`: position, is ignored if you define def.minpos and def.maxpos
|
||||
* `def`: (optional) particle definition
|
||||
|
||||
## mcl_dye.register_on_bone_meal_apply(function(pointed_thing, user))
|
||||
Called when the bone meal is applied anywhere.
|
||||
* `pointed_thing`: exact pointing location (see Minetest API), where the bone meal is applied
|
||||
* `user`: ObjectRef of the player who aplied the bone meal, can be nil!
|
|
@ -128,26 +128,35 @@ for _, row in ipairs(dyelocal.dyes) do
|
|||
end
|
||||
|
||||
-- Bone Meal
|
||||
local function bone_meal_particle(pos)
|
||||
function mcl_dye.add_bone_meal_particle(pos, def)
|
||||
if not def then
|
||||
def = {}
|
||||
end
|
||||
minetest.add_particlespawner({
|
||||
amount = 10,
|
||||
time = 0.1,
|
||||
minpos = { x = pos.x - 0.5, y = pos.y - 0.5, z = pos.z - 0.5 },
|
||||
maxpos = { x = pos.x + 0.5, y = pos.y + 0.5, z = pos.z + 0.5 },
|
||||
minvel = { x = 0, y = 0, z = 0},
|
||||
maxvel = { x = 0, y = 0, z = 0},
|
||||
minacc = { x = 0, y = 0, z = 0},
|
||||
maxacc = { x = 0, y = 0, z = 0},
|
||||
minexptime = 1,
|
||||
maxexptime = 4,
|
||||
minsize = 0.7,
|
||||
maxsize = 2.4,
|
||||
amount = def.amount or 10,
|
||||
time = def.time or 0.1,
|
||||
minpos = def.minpos or vector.subtract(pos, 0.5),
|
||||
maxpos = def.maxpos or vector.add(pos, 0.5),
|
||||
minvel = def.minvel or vector.new(0, 0, 0),
|
||||
maxvel = def.maxvel or vector.new(0, 0, 0),
|
||||
minacc = def.minacc or vector.new(0, 0, 0),
|
||||
maxacc = def.maxacc or vector.new(0, 0, 0),
|
||||
minexptime = def.minexptime or 1,
|
||||
maxexptime = def.maxexptime or 4,
|
||||
minsize = def.minsize or 0.7,
|
||||
maxsize = def.maxsize or 2.4,
|
||||
texture = "mcl_particles_bonemeal.png^[colorize:#00EE00:125", -- TODO: real MC color
|
||||
glow = 5,
|
||||
glow = def.glow or 5,
|
||||
})
|
||||
end
|
||||
|
||||
function mcl_dye.apply_bone_meal(pointed_thing)
|
||||
mcl_dye.bone_meal_callbacks = {}
|
||||
|
||||
function mcl_dye.register_on_bone_meal_apply(func)
|
||||
table.insert(mcl_dye.bone_meal_callbacks, func)
|
||||
end
|
||||
|
||||
local function apply_bone_meal(pointed_thing)
|
||||
-- Bone meal currently spawns all flowers found in the plains.
|
||||
local flowers_table_plains = {
|
||||
"mcl_flowers:dandelion",
|
||||
|
@ -183,14 +192,21 @@ function mcl_dye.apply_bone_meal(pointed_thing)
|
|||
local pos = pointed_thing.under
|
||||
local n = minetest.get_node(pos)
|
||||
if n.name == "" then return false end
|
||||
|
||||
for _, func in pairs(mcl_dye.bone_meal_callbacks) do
|
||||
if func(pointed_thing, user) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
if minetest.get_item_group(n.name, "sapling") >= 1 then
|
||||
bone_meal_particle(pos)
|
||||
mcl_dye.add_bone_meal_particle(pos)
|
||||
-- Saplings: 45% chance to advance growth stage
|
||||
if math.random(1,100) <= 45 then
|
||||
return mcl_core.grow_sapling(pos, n)
|
||||
end
|
||||
elseif minetest.get_item_group(n.name, "mushroom") == 1 then
|
||||
bone_meal_particle(pos)
|
||||
mcl_dye.add_bone_meal_particle(pos)
|
||||
-- Try to grow huge mushroom
|
||||
|
||||
-- Must be on a dirt-type block
|
||||
|
@ -240,39 +256,37 @@ function mcl_dye.apply_bone_meal(pointed_thing)
|
|||
return false
|
||||
-- Wheat, Potato, Carrot, Pumpkin Stem, Melon Stem: Advance by 2-5 stages
|
||||
elseif string.find(n.name, "mcl_farming:wheat_") then
|
||||
bone_meal_particle(pos)
|
||||
mcl_dye.add_bone_meal_particle(pos)
|
||||
local stages = math.random(2, 5)
|
||||
return mcl_farming:grow_plant("plant_wheat", pos, n, stages, true)
|
||||
elseif string.find(n.name, "mcl_farming:potato_") then
|
||||
bone_meal_particle(pos)
|
||||
mcl_dye.add_bone_meal_particle(pos)
|
||||
local stages = math.random(2, 5)
|
||||
return mcl_farming:grow_plant("plant_potato", pos, n, stages, true)
|
||||
elseif string.find(n.name, "mcl_farming:carrot_") then
|
||||
bone_meal_particle(pos)
|
||||
mcl_dye.add_bone_meal_particle(pos)
|
||||
local stages = math.random(2, 5)
|
||||
return mcl_farming:grow_plant("plant_carrot", pos, n, stages, true)
|
||||
elseif string.find(n.name, "mcl_farming:pumpkin_") then
|
||||
bone_meal_particle(pos)
|
||||
mcl_dye.add_bone_meal_particle(pos)
|
||||
local stages = math.random(2, 5)
|
||||
return mcl_farming:grow_plant("plant_pumpkin_stem", pos, n, stages, true)
|
||||
elseif string.find(n.name, "mcl_farming:melontige_") then
|
||||
bone_meal_particle(pos)
|
||||
mcl_dye.add_bone_meal_particle(pos)
|
||||
local stages = math.random(2, 5)
|
||||
return mcl_farming:grow_plant("plant_melon_stem", pos, n, stages, true)
|
||||
elseif string.find(n.name, "mcl_farming:beetroot_") then
|
||||
bone_meal_particle(pos)
|
||||
mcl_dye.add_bone_meal_particle(pos)
|
||||
-- Beetroot: 75% chance to advance to next stage
|
||||
if math.random(1, 100) <= 75 then
|
||||
return mcl_farming:grow_plant("plant_beetroot", pos, n, 1, true)
|
||||
end
|
||||
elseif n.name == "mcl_cocoas:cocoa_1" or n.name == "mcl_cocoas:cocoa_2" then
|
||||
bone_meal_particle(pos)
|
||||
mcl_dye.add_bone_meal_particle(pos)
|
||||
-- Cocoa: Advance by 1 stage
|
||||
mcl_cocoas.grow(pos)
|
||||
return true
|
||||
elseif minetest.get_item_group(n.name, "grass_block") == 1 then
|
||||
local grass_block_pos = {x = pos.x, y = pos.y + 1, z = pos.z}
|
||||
bone_meal_particle(grass_block_pos)
|
||||
-- Grass Block: Generate tall grass and random flowers all over the place
|
||||
for i = -2, 2 do
|
||||
for j = -2, 2 do
|
||||
|
@ -285,6 +299,7 @@ function mcl_dye.apply_bone_meal(pointed_thing)
|
|||
-- Randomly generate flowers, tall grass or nothing
|
||||
if math.random(1,100) <= 90 then
|
||||
-- 90% tall grass, 10% flower
|
||||
mcl_dye.add_bone_meal_particle(pos, {amount = 4})
|
||||
if math.random(1,100) <= 90 then
|
||||
local col = n2.param2
|
||||
minetest.add_node(pos, {name="mcl_flowers:tallgrass", param2=col})
|
||||
|
@ -314,24 +329,24 @@ function mcl_dye.apply_bone_meal(pointed_thing)
|
|||
|
||||
-- Double flowers: Drop corresponding item
|
||||
elseif n.name == "mcl_flowers:rose_bush" or n.name == "mcl_flowers:rose_bush_top" then
|
||||
bone_meal_particle(pos)
|
||||
mcl_dye.add_bone_meal_particle(pos)
|
||||
minetest.add_item(pos, "mcl_flowers:rose_bush")
|
||||
return true
|
||||
elseif n.name == "mcl_flowers:peony" or n.name == "mcl_flowers:peony_top" then
|
||||
bone_meal_particle(pos)
|
||||
mcl_dye.add_bone_meal_particle(pos)
|
||||
minetest.add_item(pos, "mcl_flowers:peony")
|
||||
return true
|
||||
elseif n.name == "mcl_flowers:lilac" or n.name == "mcl_flowers:lilac_top" then
|
||||
bone_meal_particle(pos)
|
||||
mcl_dye.add_bone_meal_particle(pos)
|
||||
minetest.add_item(pos, "mcl_flowers:lilac")
|
||||
return true
|
||||
elseif n.name == "mcl_flowers:sunflower" or n.name == "mcl_flowers:sunflower_top" then
|
||||
bone_meal_particle(pos)
|
||||
mcl_dye.add_bone_meal_particle(pos)
|
||||
minetest.add_item(pos, "mcl_flowers:sunflower")
|
||||
return true
|
||||
|
||||
elseif n.name == "mcl_flowers:tallgrass" then
|
||||
bone_meal_particle(pos)
|
||||
mcl_dye.add_bone_meal_particle(pos)
|
||||
-- Tall Grass: Grow into double tallgrass
|
||||
local toppos = { x=pos.x, y=pos.y+1, z=pos.z }
|
||||
local topnode = minetest.get_node(toppos)
|
||||
|
@ -342,7 +357,7 @@ function mcl_dye.apply_bone_meal(pointed_thing)
|
|||
end
|
||||
|
||||
elseif n.name == "mcl_flowers:fern" then
|
||||
bone_meal_particle(pos)
|
||||
mcl_dye.add_bone_meal_particle(pos)
|
||||
-- Fern: Grow into large fern
|
||||
local toppos = { x=pos.x, y=pos.y+1, z=pos.z }
|
||||
local topnode = minetest.get_node(toppos)
|
||||
|
@ -374,7 +389,7 @@ minetest.register_craftitem("mcl_dye:white", {
|
|||
end
|
||||
|
||||
-- Use the bone meal on the ground
|
||||
if(mcl_dye.apply_bone_meal(pointed_thing) and (not minetest.is_creative_enabled(user:get_player_name()))) then
|
||||
if (apply_bone_meal(pointed_thing, user) and (not minetest.is_creative_enabled(user:get_player_name()))) then
|
||||
itemstack:take_item()
|
||||
end
|
||||
return itemstack
|
||||
|
@ -387,7 +402,7 @@ minetest.register_craftitem("mcl_dye:white", {
|
|||
else
|
||||
pointed_thing = { above = pos, under = droppos }
|
||||
end
|
||||
local success = mcl_dye.apply_bone_meal(pointed_thing)
|
||||
local success = apply_bone_meal(pointed_thing, nil)
|
||||
if success then
|
||||
stack:take_item()
|
||||
end
|
||||
|
|
|
@ -183,7 +183,7 @@ minetest.register_entity("mcl_enchanting:book", {
|
|||
collisionbox = {0, 0, 0},
|
||||
pointable = false,
|
||||
physical = false,
|
||||
textures = {"mcl_enchanting_book_entity.png"},
|
||||
textures = {"mcl_enchanting_book_entity.png", "mcl_enchanting_book_entity.png", "mcl_enchanting_book_entity.png", "mcl_enchanting_book_entity.png", "mcl_enchanting_book_entity.png"},
|
||||
static_save = false,
|
||||
},
|
||||
_player_near = false,
|
||||
|
|
|
@ -1496,7 +1496,7 @@ local function register_dimension_biomes()
|
|||
heat_point = 100,
|
||||
humidity_point = 0,
|
||||
_mcl_biome_type = "hot",
|
||||
_mcl_palette_index = 19,
|
||||
_mcl_palette_index = 17,
|
||||
})
|
||||
|
||||
--[[ THE END ]]
|
||||
|
|
|
@ -118,17 +118,6 @@ def colorize_alpha(colormap, source, colormap_pixel, texture_size, destination):
|
|||
colorize(colormap, source, colormap_pixel, texture_size, tempfile2.name)
|
||||
os.system("composite -compose Dst_In "+source+" "+tempfile2.name+" -alpha Set "+destination)
|
||||
|
||||
# This function is unused atm.
|
||||
# TODO: Implemnt colormap extraction
|
||||
def extract_colormap(colormap, colormap_pixel, positions):
|
||||
os.system("convert -size 16x16 canvas:black "+tempfile1.name)
|
||||
x=0
|
||||
y=0
|
||||
for p in positions:
|
||||
os.system("convert "+colormap+" -crop 1x1+"+colormap_pixel+" -depth 8 "+tempfile2.name)
|
||||
os.system("composite -geometry 16x16+"+x+"+"+y+" "+tempfile2.name)
|
||||
x = x+1
|
||||
|
||||
def target_dir(directory):
|
||||
if make_texture_pack:
|
||||
return output_dir + "/" + output_dir_name
|
||||
|
@ -397,20 +386,60 @@ def convert_textures():
|
|||
colorize_alpha(FOLIAG, tex_dir+"/blocks/vine.png", "16+39", str(PXSIZE), target_dir("/mods/ITEMS/mcl_core/textures")+"/mcl_core_vine.png")
|
||||
|
||||
# Tall grass, fern (inventory images)
|
||||
pcol = "49+172" # Plains grass color
|
||||
pcol = "50+173" # Plains grass color
|
||||
colorize_alpha(GRASS, tex_dir+"/blocks/tallgrass.png", pcol, str(PXSIZE), target_dir("/mods/ITEMS/mcl_flowers/textures")+"/mcl_flowers_tallgrass_inv.png")
|
||||
colorize_alpha(GRASS, tex_dir+"/blocks/fern.png", pcol, str(PXSIZE), target_dir("/mods/ITEMS/mcl_flowers/textures")+"/mcl_flowers_fern_inv.png")
|
||||
colorize_alpha(GRASS, tex_dir+"/blocks/double_plant_fern_top.png", pcol, str(PXSIZE), target_dir("/mods/ITEMS/mcl_flowers/textures")+"/mcl_flowers_double_plant_fern_inv.png")
|
||||
colorize_alpha(GRASS, tex_dir+"/blocks/double_plant_grass_top.png", pcol, str(PXSIZE), target_dir("/mods/ITEMS/mcl_flowers/textures")+"/mcl_flowers_double_plant_grass_inv.png")
|
||||
|
||||
# TODO: Convert grass palette
|
||||
|
||||
offset = [
|
||||
[ pcol, "", "grass" ], # Default grass: Plains
|
||||
# Convert grass palette: https://minecraft.fandom.com/wiki/Tint
|
||||
grass_colors = [
|
||||
# [Coords or #Color, AdditionalTint], # Index - Minecraft biome name (MineClone2 biome names)
|
||||
["50+173"], # 0 - Plains (flat, Plains, Plains_beach, Plains_ocean, End)
|
||||
["0+255"], # 1 - Savanna (Savanna, Savanna_beach, Savanna_ocean)
|
||||
["255+255"], # 2 - Ice Spikes (IcePlainsSpikes, IcePlainsSpikes_ocean)
|
||||
["255+255"], # 3 - Snowy Taiga (ColdTaiga, ColdTaiga_beach, ColdTaiga_beach_water, ColdTaiga_ocean)
|
||||
["178+193"], # 4 - Giant Tree Taiga (MegaTaiga, MegaTaiga_ocean)
|
||||
["178+193"], # 5 - Giant Tree Taiga (MegaSpruceTaiga, MegaSpruceTaiga_ocean)
|
||||
["203+239"], # 6 - Montains (ExtremeHills, ExtremeHills_beach, ExtremeHills_ocean)
|
||||
["203+239"], # 7 - Montains (ExtremeHillsM, ExtremeHillsM_ocean)
|
||||
["203+239"], # 8 - Montains (ExtremeHills+, ExtremeHills+_snowtop, ExtremeHills+_ocean)
|
||||
["50+173"], # 9 - Beach (StoneBeach, StoneBeach_ocean)
|
||||
["255+255"], # 10 - Snowy Tundra (IcePlains, IcePlains_ocean)
|
||||
["50+173"], # 11 - Sunflower Plains (SunflowerPlains, SunflowerPlains_ocean)
|
||||
["191+203"], # 12 - Taiga (Taiga, Taiga_beach, Taiga_ocean)
|
||||
["76+112"], # 13 - Forest (Forest, Forest_beach, Forest_ocean)
|
||||
["76+112"], # 14 - Flower Forest (FlowerForest, FlowerForest_beach, FlowerForest_ocean)
|
||||
["101+163"], # 15 - Birch Forest (BirchForest, BirchForest_ocean)
|
||||
["101+163"], # 16 - Birch Forest Hills (BirchForestM, BirchForestM_ocean)
|
||||
["0+255"], # 17 - Desert and Nether (Desert, Desert_ocean, Nether)
|
||||
["76+112", "#28340A"], # 18 - Dark Forest (RoofedForest, RoofedForest_ocean)
|
||||
["#90814d"], # 19 - Mesa (Mesa, Mesa_sandlevel, Mesa_ocean, )
|
||||
["#90814d"], # 20 - Mesa (MesaBryce, MesaBryce_sandlevel, MesaBryce_ocean)
|
||||
["#90814d"], # 21 - Mesa (MesaPlateauF, MesaPlateauF_grasstop, MesaPlateauF_sandlevel, MesaPlateauF_ocean)
|
||||
["#90814d"], # 22 - Mesa (MesaPlateauFM, MesaPlateauFM_grasstop, MesaPlateauFM_sandlevel, MesaPlateauFM_ocean)
|
||||
["0+255"], # 23 - Shattered Savanna (or Savanna Plateau ?) (SavannaM, SavannaM_ocean)
|
||||
["12+36"], # 24 - Jungle (Jungle, Jungle_shore, Jungle_ocean)
|
||||
["12+36"], # 25 - Modified Jungle (JungleM, JungleM_shore, JungleM_ocean)
|
||||
["12+61"], # 26 - Jungle Edge (JungleEdge, JungleEdge_ocean)
|
||||
["12+61"], # 27 - Modified Jungle Edge (JungleEdgeM, JungleEdgeM_ocean)
|
||||
["#6A7039"], # 28 - Swamp (Swampland, Swampland_shore, Swampland_ocean)
|
||||
["25+25"], # 29 - Mushroom Fields and Mushroom Field Shore (MushroomIsland, MushroomIslandShore, MushroomIsland_ocean)
|
||||
]
|
||||
for o in offset:
|
||||
colorize(GRASS, tex_dir+"/blocks/grass_top.png", o[0], str(PXSIZE), target_dir("/mods/ITEMS/mcl_core/textures")+"/default_"+o[2]+".png")
|
||||
colorize_alpha(GRASS, tex_dir+"/blocks/grass_side_overlay.png", o[0], str(PXSIZE), target_dir("/mods/ITEMS/mcl_core/textures")+"/default_"+o[2]+"_side.png")
|
||||
|
||||
grass_palette_file = target_dir("/mods/ITEMS/mcl_core/textures") + "/mcl_core_palette_grass.png"
|
||||
os.system("convert -size 16x16 canvas:transparent " + grass_palette_file)
|
||||
|
||||
for i, color in enumerate(grass_colors):
|
||||
if color[0][0] == "#":
|
||||
os.system("convert -size 1x1 xc:\"" + color[0] + "\" " + tempfile1.name + ".png")
|
||||
else:
|
||||
os.system("convert " + GRASS + " -crop 1x1+" + color[0] + " " + tempfile1.name + ".png")
|
||||
|
||||
if len(color) > 1:
|
||||
os.system("convert " + tempfile1.name + ".png \\( -size 1x1 xc:\"" + color[1] + "\" \\) -compose blend -define compose:args=50,50 -composite " + tempfile1.name + ".png")
|
||||
|
||||
os.system("convert " + grass_palette_file + " \\( " + tempfile1.name + ".png -geometry +" + str(i % 16) + "+" + str(int(i / 16)) + " \\) -composite " + grass_palette_file)
|
||||
|
||||
# Metadata
|
||||
if make_texture_pack:
|
||||
|
|
|
@ -13,6 +13,7 @@ local colors = {
|
|||
["3D Models"] = "0x0019FF",
|
||||
["Textures"] = "0xFF9705",
|
||||
["Translations"] = "0x00FF60",
|
||||
["Funders"] = "0xF7FF00",
|
||||
["Special thanks"] = "0x00E9FF",
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue