forked from VoxeLibre/VoxeLibre
Cauldrons API, object-based; changes to mcl_buckets and mcl_potions for interaction with water cauldron.
This commit is contained in:
parent
1b0b5fc733
commit
cf194ed51a
|
@ -93,6 +93,14 @@ function mcl_buckets.register_liquid(def)
|
|||
-- Check if pointing to a buildable node
|
||||
--local item = itemstack:get_name()
|
||||
|
||||
local into_cauldron
|
||||
local bucket_content = def._bucket_content
|
||||
-- TODO: guard with test for mcl_cauldrons
|
||||
into_cauldron = mcl_cauldrons.get_cauldron(place_pos)
|
||||
if into_cauldron and not into_cauldron:accepts_substance(bucket_content) then
|
||||
into_cauldron = nil
|
||||
end
|
||||
|
||||
if def.extra_check and def.extra_check(place_pos, user) == true and nodedef and nodedef.buildable_to then
|
||||
-- buildable; replace the node
|
||||
local pns = user:get_player_name()
|
||||
|
@ -104,6 +112,11 @@ function mcl_buckets.register_liquid(def)
|
|||
if mod_doc and doc.entry_exists("nodes", node_place) then
|
||||
doc.mark_entry_as_revealed(user:get_player_name(), "nodes", node_place)
|
||||
end
|
||||
elseif into_cauldron then
|
||||
if into_cauldron:fill_levels(bucket_content, into_cauldron.BUCKETFUL) then
|
||||
into_cauldron:update_node()
|
||||
sound_place("mcl_core:water_source", place_pos)
|
||||
end
|
||||
else
|
||||
-- not buildable to; place the liquid above
|
||||
-- check if the node above can be replaced
|
||||
|
@ -201,6 +214,8 @@ minetest.register_craftitem("mcl_buckets:bucket_empty", {
|
|||
-- Check if pointing to a liquid source
|
||||
local liquiddef = mcl_buckets.liquids[nn]
|
||||
local new_bucket
|
||||
local from_cauldron
|
||||
from_cauldron = mcl_cauldrons.get_cauldron(pointed_thing.under)
|
||||
if liquiddef ~= nil and liquiddef.itemname ~= nil and (nn == liquiddef.source_take) then
|
||||
|
||||
-- Fill bucket, but not in Creative Mode
|
||||
|
@ -218,8 +233,27 @@ minetest.register_craftitem("mcl_buckets:bucket_empty", {
|
|||
doc.mark_entry_as_revealed(user:get_player_name(), "nodes", nn)
|
||||
end
|
||||
|
||||
elseif from_cauldron then
|
||||
-- Cauldron
|
||||
--[[
|
||||
elseif minetest.get_item_group(nn, "cauldron") then
|
||||
new_bucket = mcl_cauldrons.take_cauldron(pointed_thing.under, new_bucket, user)
|
||||
--]]
|
||||
if from_cauldron:drain_levels("water", from_cauldron.BUCKETFUL) then
|
||||
-- succeeds only if a water cauldron with enough content.
|
||||
from_cauldron:update_node()
|
||||
if not minetest.is_creative_enabled(user:get_player_name()) then
|
||||
new_bucket = ItemStack({name = "mcl_buckets:bucket_water"})
|
||||
end
|
||||
sound_take("mcl_core:water_source", from_cauldron.pos)
|
||||
elseif from_cauldron:drain_levels("river_water", from_cauldron.BUCKETFUL) then
|
||||
-- succeeds only if river water cauldron with enough content.
|
||||
from_cauldron:update_node()
|
||||
if not minetest.is_creative_enabled(user:get_player_name()) then
|
||||
new_bucket = ItemStack({name = "mcl_buckets:bucket_river_water"})
|
||||
end
|
||||
sound_take("mcl_core:river_water_source", from_cauldron.pos)
|
||||
end
|
||||
end
|
||||
|
||||
-- Add liquid bucket and put it into inventory, if possible.
|
||||
|
@ -227,6 +261,27 @@ minetest.register_craftitem("mcl_buckets:bucket_empty", {
|
|||
if minetest.is_creative_enabled(user:get_player_name()) then --TODO
|
||||
itemstack:take_item()
|
||||
end
|
||||
|
||||
-- copied and edited from empty bucket code.
|
||||
if not minetest.is_creative_enabled(user:get_player_name()) then
|
||||
-- Add water bucket and put it into inventory, if possible.
|
||||
-- Drop water bucket otherwise.
|
||||
if itemstack:get_count() == 1 then
|
||||
return new_bucket
|
||||
else
|
||||
local inv = user:get_inventory()
|
||||
if inv:room_for_item("main", new_bucket) then
|
||||
inv:add_item("main", new_bucket)
|
||||
else
|
||||
minetest.add_item(user:get_pos(), new_bucket)
|
||||
end
|
||||
itemstack:take_item()
|
||||
return itemstack
|
||||
end
|
||||
else
|
||||
return
|
||||
end
|
||||
|
||||
end,
|
||||
_on_dispense = function(stack, pos, droppos, dropnode, dropdir)
|
||||
-- Fill empty bucket with liquid or drop bucket if no liquid
|
||||
|
|
|
@ -39,7 +39,8 @@ if mod_mcl_core then
|
|||
name = S("Lava Bucket"),
|
||||
longdesc = S("A bucket can be used to collect and release liquids. This one is filled with hot lava, safely contained inside. Use with caution."),
|
||||
usagehelp = S("Get in a safe distance and place the bucket to empty it and create a lava source at this spot. Don't burn yourself!"),
|
||||
tt_help = S("Places a lava source")
|
||||
tt_help = S("Places a lava source"),
|
||||
_bucket_content = "lava"
|
||||
})
|
||||
|
||||
-- Water bucket
|
||||
|
@ -66,11 +67,14 @@ if mod_mcl_core then
|
|||
-- Pour water into cauldron
|
||||
if minetest.get_item_group(nn, "cauldron") ~= 0 then
|
||||
-- Put water into cauldron
|
||||
print("extra check cauldron")
|
||||
--[[
|
||||
if nn ~= "mcl_cauldrons:cauldron_3" then
|
||||
mcl_cauldrons.set_cauldron_level(pos, "water", 3)
|
||||
end
|
||||
sound_place("mcl_core:water_source", pos)
|
||||
return false
|
||||
--]]
|
||||
-- Evaporate water if used in Nether (except on cauldron)
|
||||
else
|
||||
local dim = mcl_worlds.pos_to_dimension(pos)
|
||||
|
@ -81,6 +85,7 @@ if mod_mcl_core then
|
|||
end
|
||||
end,
|
||||
groups = { water_bucket = 1 },
|
||||
_bucket_content = "water",
|
||||
})
|
||||
end
|
||||
|
||||
|
@ -109,11 +114,13 @@ if mod_mclx_core then
|
|||
-- Pour into cauldron
|
||||
if minetest.get_item_group(nn, "cauldron") ~= 0 then
|
||||
-- Put water into cauldron
|
||||
--[[
|
||||
if nn ~= "mcl_cauldrons:cauldron_3r" then
|
||||
mcl_cauldrons.set_cauldron(pos, "river_water", 3)
|
||||
end
|
||||
sound_place("mcl_core:water_source", pos)
|
||||
return false
|
||||
--]]
|
||||
else
|
||||
-- Evaporate water if used in Nether (except on cauldron)
|
||||
local dim = mcl_worlds.pos_to_dimension(pos)
|
||||
|
@ -124,6 +131,7 @@ if mod_mclx_core then
|
|||
end
|
||||
end,
|
||||
groups = { water_bucket = 1 },
|
||||
_bucket_content = "river_water",
|
||||
})
|
||||
end
|
||||
|
||||
|
|
|
@ -25,4 +25,185 @@ def can have these fields:
|
|||
* texture: texture of the flowing liquid e.g: "mcl_core_water_flowing.png"
|
||||
|
||||
## mcl_cauldrons.registered_cauldrons
|
||||
Table containing chauldrons def indexed by name.
|
||||
Table containing chauldrons def indexed by name.
|
||||
|
||||
|
||||
|
||||
|
||||
Behavior
|
||||
--------
|
||||
|
||||
Behavior should mimick Cauldron from Minecraft Java Edition 1.13.
|
||||
|
||||
Incomplete notes based on [Cauldron entry from Minecraft wiki](https://minecraft.fandom.com/wiki/Cauldron), with edits derived from what historical/version logs found:
|
||||
|
||||
* May be mined
|
||||
* Drops (empty) cauldron item if mined with pickaxe.
|
||||
* No drop if mined with anything else.
|
||||
* When destroyed/mined, contents are lost.
|
||||
* May be empty
|
||||
* Completely filled with water by using water bucket (and bucket empties).
|
||||
* Cannot be filled with fish bucket (despite water), causes normal node placing instead.
|
||||
* Add one level of water with water bottle (and bottle empties).
|
||||
* Slowly fills with water when rained upon.
|
||||
* May hold water
|
||||
* When full, completely emptied by using empty bucket (and bucket fills).
|
||||
* Add one level of water with water bottle (and bottle empties).
|
||||
* Remove one level of water with glass bottle (and bottle fills).
|
||||
* Slowly fills with water when rained upon.
|
||||
* Does not absorb explosion.
|
||||
* Does not make sounds/particles/bubbles at all, including when jumping in.
|
||||
* Does not damage endermen, striders, blazes.
|
||||
* Does not deal drowning damage.
|
||||
* Does not allow fish to breathe.
|
||||
* Does not allow player to float or swim (emergent from height property?).
|
||||
* Does not count as a riptide source (for Trident).
|
||||
* Does not allow any interaction with sponge.
|
||||
* Washes dye off items, by using (right-clicking) item into cauldron.
|
||||
- Reduces water level by one with each washing.
|
||||
- Removes dye from leather armor.
|
||||
- Removes dye from shulker box.
|
||||
- Removes dye from top-most layer of banner.
|
||||
- Water remains undyed.
|
||||
* Extinguishes entities on fire:
|
||||
- Entities emit black particles as fire is extinguished.
|
||||
- Entities must reach the actual water (fall into cauldron).
|
||||
- Reduces water level by one with each entity extinguished.
|
||||
- Extinguishes flaming arrows stuck into side of cauldron (not an entity, so does not consume water level).
|
||||
* Attached redstone comparator emits signal strength proportional to water level (0=empty .. 3=full).
|
||||
* May not hold:
|
||||
* milk
|
||||
* honey
|
||||
* food items in a bowl (mushroom stew, beetroot soup, rabbit soup, suspicious stew)
|
||||
* Water texture might vary with biome?
|
||||
|
||||
### Other Editions and Future Notes (up to 1.17)
|
||||
|
||||
Particular behaviors to avoid as they contradict Minecraft JE 1.13.
|
||||
Incomplete notes based on wiki and logs:
|
||||
|
||||
* BEDROCK - may hold potion.
|
||||
* BEDROCK - may add dyes (color-mixing supported) to make dyed water, which can dye leather armor or leather horse armor.
|
||||
* 1.14 - Cauldrons are job site blocks for Leatherworker (villager).
|
||||
* 1.17 - Filled cauldrons are not job site blocks (only empty cauldrons).
|
||||
* 1.17 - May be filled with lava (affects light level, burning of entities).
|
||||
* 1.17 - May be filled with powder snow (affects extinguishing).
|
||||
* 1.17 - May collect water and lava from Pointed Dripstone.
|
||||
* 1.17 - Lava Bucket and Powder Snow Bucket may empty into any filled cauldron (old contents lost).
|
||||
|
||||
|
||||
|
||||
Node Definitions
|
||||
----------------
|
||||
|
||||
Cauldron definitions extends the node definition (as accepted by `minetest.register_node()`) with the following keys:
|
||||
|
||||
* `.groups.cauldron`: number = 1 - indicates cauldron behavior
|
||||
* `.groups.cauldron_filled`: number = fill level of cauldron
|
||||
* `.groups.cauldron_water`: number = 1 if contains water, else 0
|
||||
* `.groups.cauldron_river_water`: number = 1 if contains river water, else 0
|
||||
* `._cauldron_content`: string = substance in cauldron
|
||||
|
||||
### `mcl_cauldrons.registered_cauldrons`
|
||||
Table containing cauldron definitions, indexed by name.
|
||||
|
||||
### `mcl_cauldrons.register_cauldron(cauldron_name, cauldron_def)`
|
||||
Register cauldron node definition. Ultimately passed to `minetest.register_node()`, but also maintains a mod-local `mcl_cauldrons.registered_cauldrons` table.
|
||||
|
||||
|
||||
Misc
|
||||
----
|
||||
|
||||
### `mcl_cauldrons.CauldronRef`
|
||||
Prototype ("class") for interacting with cauldrons at run-time.
|
||||
|
||||
### `mcl_cauldrons.get_cauldron(pos)`
|
||||
* `pos`: position of node in world
|
||||
* If you're lost in the API, this is where you want to start.
|
||||
* Returns an instance of CauldronRef based on node.
|
||||
* Returns `nil` if not a cauldron.
|
||||
* Alias for `CauldronRef.make_cauldron_ref`
|
||||
|
||||
### `mcl_cauldrons.set_cauldron(pos, cauldron_ref)`
|
||||
* `pos`: world node position
|
||||
* `cauldron_ref`: CauldronRef instance
|
||||
* Update world node to be consistent with CauldronRef (i.e. "commit" CauldronRef to the world)
|
||||
|
||||
|
||||
|
||||
|
||||
`CauldronRef`
|
||||
-------------
|
||||
|
||||
Object-based interaction with cauldrons in the game.
|
||||
Cauldron behavior is based on Cauldron in Minecraft Java Edition 1.13.
|
||||
|
||||
In general, the object should be abandoned after its contents are transferred to the world (i.e. after `update_node()` or after `make_node()` contents applied with `minetest.set_node()`).
|
||||
Exceptions apply if you know what you're doing with the reference.
|
||||
|
||||
### Constants
|
||||
* `BUCKETFUL` - number of levels changed by using a bucket (historically 3).
|
||||
* `BOTTLEFUL` - number of levels changed by using a bottle (historically 1).
|
||||
|
||||
### Prototype ("Class") Methods
|
||||
* `make_cauldron_ref(pos)`: table, new CauldonRef instance
|
||||
* `pos`: position of node in world
|
||||
* Returns an instance of CauldronRef based on node.
|
||||
* Returns `nil` if not a cauldron.
|
||||
* `find_nodedef(substance, fill_level)`: table, registered cauldron node definition
|
||||
* `substance`: string - desired content of cauldron
|
||||
* `fill_level`: number - desired fill level of cauldron
|
||||
* Scans registered cauldron nodes for cauldron defintion that best fits the parameters.
|
||||
|
||||
### Instance Methods
|
||||
* `is_empty()`: returns boolean - test if cauldron is empty
|
||||
* `accept_substance(substance)`: returns boolean
|
||||
* `substance`: string - value representing a cauldron substance
|
||||
* `get_substance()`: returns string - contents of cauldron, may be nil
|
||||
* `set_substance(substance)`:
|
||||
* `substance`: string - cauldron substance (pending)
|
||||
* Effect is **NOT** immediate; change is stored for `make_node`.
|
||||
* `get_level(substance)`: returns number - current fill level of cauldron
|
||||
* `substance`: string - cauldron substance
|
||||
* Can also be test for cauldron containing substance (test value > 0)
|
||||
* 0 does not mean cauldron is empty, it means no amount of *this* substance exists in the cauldron.
|
||||
* e.g. cauldron of "river\_water" returns 0 level for "water", as only "river\_water" is available and no "water".
|
||||
* use `is_empty()` to test for an empty cauldron (cauldron actually has nothing inside).
|
||||
* `set_level(substance, fill_level)`
|
||||
* `substance`: string - substance to be contained in cauldron, `nil` to preserve content
|
||||
* `fill_level`: number - fill level of the cauldron (with substance)
|
||||
* Change cauldron contents, bypassing fill/drain rules.
|
||||
* Reduces to empty cauldron if `substance == "empty"` or `fill_level == 0`.
|
||||
* Effect is **NOT** immediate; change is stored for `make_node`.
|
||||
* `fill_levels(substance, change_levels)`: returns boolean
|
||||
* `substance`: string - substance to fill cauldron, `nil` to indicate current contents
|
||||
* `change_levels`: number - number of levels to add
|
||||
* Fills cauldron with a substance subject to game rules:
|
||||
* If cauldron contains the same substance, add more levels
|
||||
* If cauldron contains different substance (or is empty), the old contents are lost during filling.
|
||||
* Maximum of 3 levels
|
||||
* Fractional `change_levels` indicates probability of using the next greater whole number (the lesser whole number may be treated as guaranteed minimum);
|
||||
e.g. 0.4 means 40% chance to fill with 1 (60% with 0);
|
||||
1.65 means 65% chance to fill with 2 (35% with 1).
|
||||
* Returns true if cauldron successfully changed (fill succeeded);
|
||||
returns false if cauldron did not or could not change (fill failed).
|
||||
* Effect is **NOT** immediate; change is stored for `make_node`.
|
||||
* `drain_levels(substance, change_levels)`: returns boolean
|
||||
* `substance`: string - substance to fill cauldron, `nil` to specifiy current content
|
||||
* `change_levels`: number - number of levels to add
|
||||
* Drains cauldron of substance subject to game rules:
|
||||
* Fails if specified substance is not in cauldron.
|
||||
* Fails if not enough levels are in the cauldron (asking for too much).
|
||||
* Fractional `change_levels` for probabilistic drain (see `fill_levels`).
|
||||
* Returns true if cauldron successfully changed (drain succeeded);
|
||||
returns false if cauldron did not or could not change (drain failed).
|
||||
* Effect is **NOT** immediate; change is stored for `make_node`.
|
||||
* `make_node()`: returns node { name, param1, param2 }
|
||||
* Data-based approach to updating cauldron in world (caller may make additional modifications to return value before passing to `minetest.set_node()`).
|
||||
* Generated from stored internal states (get, set, fill, drain).
|
||||
* Suitable for passing to `minetest.set_node()`
|
||||
* `update_node()`: update node in world with cauldron's internal state.
|
||||
* Imperative approach to updating cauldron in world (effect is **IMMEDIATE**).
|
||||
* Updates cauldron based on stored internal states (set, fill, drain).
|
||||
* Directly invokes `minetest.set_node()`.
|
||||
|
||||
|
|
|
@ -1,5 +1,11 @@
|
|||
local has_doc = minetest.get_modpath(minetest.get_current_modname())
|
||||
|
||||
-- API for mcl_cauldrons (Cauldron)
|
||||
|
||||
-- namespace.
|
||||
mcl_cauldrons.registered_cauldrons = {}
|
||||
|
||||
--[[
|
||||
local function survival_give(inv, original_item, itemstack)
|
||||
if inv:room_for_item("main", itemstack) then
|
||||
inv:add_item("main", itemstack)
|
||||
|
@ -156,4 +162,343 @@ function mcl_cauldrons.take_small_cauldron(pos, itemstack, user, sounds)
|
|||
end
|
||||
return itemstack
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--]]
|
||||
|
||||
|
||||
--------------------------------
|
||||
|
||||
|
||||
|
||||
-- Symbolic constants for changing levels by vessel capacity.
|
||||
|
||||
mcl_cauldrons.BUCKETFUL = 3
|
||||
mcl_cauldrons.BOTTLEFUL = 1
|
||||
|
||||
|
||||
|
||||
-----------------------
|
||||
---- Base Cauldron ----
|
||||
-----------------------
|
||||
---- base prototype for cauldrons
|
||||
|
||||
local BaseCauldronRef = {
|
||||
BUCKETFUL = mcl_cauldrons.BUCKETFUL,
|
||||
BOTTLEFUL = mcl_cauldrons.BOTTLEFUL,
|
||||
}
|
||||
|
||||
---- class methods
|
||||
|
||||
-- find cauldron node defintion best fitting substance and fill_level.
|
||||
BaseCauldronRef.find_nodedef = function (Self, substance, fill_level)
|
||||
-- fill_level == nil for any/first cauldron with substance.
|
||||
if (fill_level == 0) or (substance == "empty") then
|
||||
-- reduce to empty cauldron.
|
||||
substance = nil
|
||||
end
|
||||
local found
|
||||
for visit_name, visit_def in pairs(mcl_cauldrons.registered_cauldrons) do
|
||||
if (visit_def._cauldron_content == substance) then
|
||||
if (fill_level == nil) or (visit_def.groups.cauldron_filled == fill_level) then
|
||||
-- any/first fill level, or specific match
|
||||
found = visit_def
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
return found
|
||||
end
|
||||
|
||||
-- Instantiate BaseCauldronRef (or child prototype) from world node position.
|
||||
BaseCauldronRef.make_cauldron_ref = function (Self, pos)
|
||||
local livenode = minetest.get_node(pos)
|
||||
if (minetest.get_item_group(livenode.name, "cauldron") == 0) then
|
||||
-- error, cannot make CauldronRef
|
||||
return nil
|
||||
end
|
||||
local nodedef = mcl_cauldrons.registered_cauldrons[livenode.name]
|
||||
local instance = Self:new(pos, livenode, nodedef)
|
||||
return instance
|
||||
end
|
||||
|
||||
-- Update world node from BaseCauldronRef (or child prototype) instance.
|
||||
BaseCauldronRef.set_cauldron_ref = function (Self, pos, cauldron_ref)
|
||||
-- do any other prepatory work.
|
||||
-- pass to module-scope function.
|
||||
mcl_cauldrons.set_cauldron(pos, cauldron_ref)
|
||||
end
|
||||
|
||||
-- Instantiate BaseCauldronRef
|
||||
BaseCauldronRef.new = function (Self, pos, livenode, nodedef)
|
||||
local instance = {
|
||||
__index = Self,
|
||||
pos = pos,
|
||||
livenode = livenode,
|
||||
nodedef = nodedef,
|
||||
-- specific behavior
|
||||
specific = nil,
|
||||
pending_substance = nil,
|
||||
pending_level = nil,
|
||||
}
|
||||
setmetatable(instance, instance)
|
||||
return instance
|
||||
end
|
||||
|
||||
|
||||
---- instance methods
|
||||
|
||||
-- test cauldron is empty (no contents).
|
||||
function BaseCauldronRef:is_empty () -- boolean
|
||||
if self.pending_level == 0 then
|
||||
return true
|
||||
elseif (minetest.get_item_group(self.livenode.name, "cauldron_filled") == 0) then
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- test cauldron accepts substance as its content.
|
||||
function BaseCauldronRef:accepts_substance (substance) -- boolean
|
||||
local found_nodedef = self:find_nodedef(substance, 1)
|
||||
return (found_nodedef ~= nil)
|
||||
end
|
||||
|
||||
-- identify contents of cauldron.
|
||||
function BaseCauldronRef:get_substance () -- string
|
||||
if self.pending_substance then
|
||||
return self.pending_substance
|
||||
else
|
||||
return self.nodedef._cauldron_content or "empty"
|
||||
end
|
||||
end
|
||||
|
||||
-- set contents of cauldron.
|
||||
function BaseCauldronRef:set_substance (substance) -- nil
|
||||
self.pending_substance = substance
|
||||
end
|
||||
|
||||
-- maximum capacity (levels) of cauldron.
|
||||
function BaseCauldronRef:get_capacity (substance)
|
||||
return 3
|
||||
end
|
||||
|
||||
-- get fill level of cauldron.
|
||||
function BaseCauldronRef:get_level (substance) -- number
|
||||
if substance == nil then
|
||||
substance = self:get_substance()
|
||||
end
|
||||
if self:get_substance() == substance then
|
||||
-- matching substance
|
||||
if self.pending_level then
|
||||
return self.pending_level
|
||||
else
|
||||
-- current level.
|
||||
return minetest.get_item_group(self.livenode.name, "cauldron_filled")
|
||||
end
|
||||
else
|
||||
-- different substance.
|
||||
if self.pending_level then
|
||||
return self.pending_level
|
||||
else
|
||||
-- inconsistent state; use 0 for now.
|
||||
return 0
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- set fill level of cauldron, bypassing fill/drain rules.
|
||||
function BaseCauldronRef:set_level (substance, fill_level) -- nil
|
||||
if substance then
|
||||
self.pending_substance = substance
|
||||
end
|
||||
self.pending_level = fill_level
|
||||
end
|
||||
|
||||
-- add levels subject to game's filling rules.
|
||||
function BaseCauldronRef:fill_levels (substance, change_levels) -- boolean
|
||||
-- base rules:
|
||||
-- 1. Same substance, add more.
|
||||
-- 2. Different substance, replace.
|
||||
-- 3. Constrain levels within 0 through 3.
|
||||
if change_levels <= 0 then
|
||||
-- invalid change.
|
||||
return false
|
||||
end
|
||||
local old_substance = self:get_substance()
|
||||
if substance == nil then
|
||||
-- substance == nil => do not change substance
|
||||
substance = old_substance
|
||||
end
|
||||
local old_level = self:get_level()
|
||||
local whole, fraction = math.modf(change_levels)
|
||||
local new_level
|
||||
if old_substance == substance then
|
||||
-- same substance, add more.
|
||||
new_level = old_level + whole
|
||||
else
|
||||
-- different substance, lose current contents.
|
||||
new_level = whole
|
||||
end
|
||||
-- probabilistic increase to next whole number.
|
||||
if fraction > 0 then
|
||||
if math.random() < fraction then
|
||||
new_level = new_level + 1
|
||||
end
|
||||
end
|
||||
-- limit 0 through 3
|
||||
new_level = math.max(0, math.min(new_level, 3))
|
||||
-- store pending state.
|
||||
self:set_level(substance, new_level)
|
||||
-- update world node.
|
||||
--return self:update_node()
|
||||
return true
|
||||
end
|
||||
|
||||
-- remove levels subject to game's draining rules.
|
||||
function BaseCauldronRef:drain_levels (substance, change_levels) -- boolean
|
||||
-- base rules:
|
||||
-- 1. Different substance, do nothing.
|
||||
-- 2. Insufficient amount, do nothing.
|
||||
-- 3. (same substance of sufficient amount) drain.
|
||||
-- 3. Constrain levels within 0 through 3.
|
||||
if change_levels <= 0 then
|
||||
-- invalid change.
|
||||
return false
|
||||
end
|
||||
local old_substance = self:get_substance()
|
||||
if substance == nil then
|
||||
-- substance == nil => do not change substance
|
||||
substance = old_substance
|
||||
end
|
||||
-- different substance, fail.
|
||||
if old_substance ~= substance then
|
||||
return false
|
||||
end
|
||||
-- insufficient amount, fail.
|
||||
local old_level = self:get_level()
|
||||
if change_levels > old_level then
|
||||
return false
|
||||
end
|
||||
-- apply change
|
||||
local whole, fraction = math.modf(change_levels)
|
||||
local new_level
|
||||
new_level = old_level - whole
|
||||
-- probabilistic decrease to previous whole number.
|
||||
if fraction > 0 then
|
||||
if math.random() < fraction then
|
||||
new_level = new_level - 1
|
||||
end
|
||||
end
|
||||
-- limit 0 through 3
|
||||
new_level = math.max(0, math.min(new_level, 3))
|
||||
-- store pending state.
|
||||
self:set_level(substance, new_level)
|
||||
-- update world node.
|
||||
--return self:update_node()
|
||||
return true
|
||||
end
|
||||
|
||||
-- After state changes are queued up for the cauldron (set, fill, drain),
|
||||
-- either the caller:
|
||||
-- a. calls make_node() and passes the return value on to minetest.set_node().
|
||||
-- OR
|
||||
-- b. calls update_node() and ends interaction with CauldronRef.
|
||||
|
||||
-- generate node table from stored state (functional approach).
|
||||
function BaseCauldronRef:make_node () -- table { name, param1, param2 }
|
||||
-- determine node {name,param1,param2} from pending state.
|
||||
local substance = self.pending_substance
|
||||
local fill_level = self.pending_level
|
||||
if (substance == nil) and (fill_level == nil) then
|
||||
-- no change.
|
||||
return self.livenode
|
||||
end
|
||||
-- get default values from current node.
|
||||
if substance == nil then
|
||||
substance = self.nodedef._cauldron_content
|
||||
end
|
||||
if fill_level == nil then
|
||||
fill_level = self.nodedef.groups.cauldron_filled
|
||||
end
|
||||
if (fill_level == 0) or (substance == "empty") then
|
||||
-- parameters for the empty cauldron.
|
||||
substance = nil
|
||||
fill_level = nil
|
||||
end
|
||||
local pending_nodename
|
||||
local pending_param1
|
||||
local pending_param2
|
||||
local found_nodedef = self:find_nodedef(substance, fill_level)
|
||||
pending_nodename = found_nodedef.name
|
||||
pending_param1 = self.livenode.param1 or 0
|
||||
pending_param2 = self.livenode.param2 or 0
|
||||
if pending_nodename then
|
||||
local node = {
|
||||
name = pending_nodename,
|
||||
param1 = pending_param1,
|
||||
param2 = pending_param2,
|
||||
}
|
||||
return node
|
||||
else
|
||||
-- could not determine new node; no change.
|
||||
return self.livenode
|
||||
end
|
||||
end
|
||||
|
||||
-- update world from stored state (imperative approach).
|
||||
function BaseCauldronRef:update_node ()
|
||||
-- subject to prototype-inheritance.
|
||||
self:set_cauldron_ref(self.pos, self)
|
||||
end
|
||||
|
||||
|
||||
---------------------------
|
||||
---- Standard Cauldron ----
|
||||
---------------------------
|
||||
|
||||
-- standard cauldron inherits BaseCauldronRef as-is.
|
||||
|
||||
local CauldronRef = { __index=BaseCauldronRef }
|
||||
setmetatable(CauldronRef, CauldronRef)
|
||||
mcl_cauldrons.CauldronRef = CauldronRef
|
||||
|
||||
|
||||
|
||||
----------------------------
|
||||
---- Mod-level functions
|
||||
----------------------------
|
||||
|
||||
-- instantiate CauldronRef based on world node.
|
||||
function mcl_cauldrons.get_cauldron (pos)
|
||||
return CauldronRef:make_cauldron_ref(pos)
|
||||
end
|
||||
|
||||
-- Update world node to represent CauldronRef instance.
|
||||
function mcl_cauldrons.set_cauldron (pos, cauldron_ref)
|
||||
local node = cauldron_ref:make_node()
|
||||
if node ~= cauldron_ref.livenode then
|
||||
-- changed.
|
||||
minetest.set_node(pos, node)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
----------------------
|
||||
---- Registration ----
|
||||
----------------------
|
||||
|
||||
function mcl_cauldrons.register_cauldron_node (nodename, cauldron_def, doc_alias)
|
||||
minetest.register_node(nodename, cauldron_def)
|
||||
mcl_cauldrons.registered_cauldrons[nodename] = cauldron_def
|
||||
if doc_alias and has_doc then
|
||||
doc.add_entry_alias("nodes", doc_alias, "nodes", nodename)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -0,0 +1,167 @@
|
|||
-- mod-scope (pseudo-global) environment: S, modname, modpath, has_doc
|
||||
|
||||
-- Standard Cauldron
|
||||
|
||||
-- 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
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
mcl_cauldrons.cauldron_nodeboxes = {}
|
||||
for w=0,3 do
|
||||
mcl_cauldrons.cauldron_nodeboxes[w] = create_cauldron_nodebox(w)
|
||||
end
|
||||
|
||||
|
||||
-- Allow for writing inheritance-based definitions.
|
||||
-- No metatable, as minetest.register_node() breaks/overwrites metatable.
|
||||
-- Works for declarative objects as they don't change after instantiation.
|
||||
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 result[k] = v end
|
||||
return result
|
||||
end
|
||||
-- note: defined as global, but should have ended up in mod-specific environment.
|
||||
|
||||
|
||||
------------------------
|
||||
---- Empty Cauldron ----
|
||||
------------------------
|
||||
|
||||
mcl_cauldrons.cauldron_empty = {
|
||||
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 = mcl_cauldrons.cauldron_nodeboxes[0],
|
||||
collision_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,
|
||||
}
|
||||
mcl_cauldrons.register_cauldron_node("mcl_cauldrons:cauldron", mcl_cauldrons.cauldron_empty)
|
||||
|
||||
|
||||
--- Water Cauldrons ---
|
||||
dosubfile("cauldron_water.lua")
|
||||
|
||||
|
||||
--- River Water Cauldrons ---
|
||||
if mclx_core then
|
||||
dosubfile("cauldron_river_water.lua")
|
||||
end
|
||||
|
||||
|
||||
--- other registration ---
|
||||
-- crafting
|
||||
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" },
|
||||
}
|
||||
})
|
||||
|
||||
-- Active Block Modifier
|
||||
|
||||
--[[
|
||||
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
|
||||
})
|
||||
--]]
|
||||
|
||||
-- extinguish fire for entities in cauldron
|
||||
minetest.register_abm({
|
||||
label = "cauldrons",
|
||||
nodenames = {"group:cauldron_water", "group:cauldron_river_water"},
|
||||
interval = 0.5,
|
||||
chance = 1,
|
||||
action = function(pos, node)
|
||||
local cauldron
|
||||
local EXTINGUISH_RADIUS = 0.4
|
||||
for _, obj in pairs(minetest.get_objects_inside_radius(pos, EXTINGUISH_RADIUS)) do
|
||||
if mcl_burning.is_burning(obj) then
|
||||
if not cauldron then
|
||||
-- instantiate when needed.
|
||||
cauldron = mcl_cauldrons.get_cauldron(pos)
|
||||
end
|
||||
mcl_burning.extinguish(obj)
|
||||
cauldron:drain_levels(nil, 1)
|
||||
local node = cauldron:make_node()
|
||||
minetest.swap_node(pos, node)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
})
|
||||
|
||||
|
||||
-- Backwards compability.
|
||||
local aliases = {
|
||||
-- key=old/deprecated nodename, value=current nodename
|
||||
["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 old_nodename, current_nodename in pairs(aliases) do
|
||||
minetest.register_alias(old_nodename, current_nodename)
|
||||
end
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
-- Node definitions to implement River Water Cauldron
|
||||
-- expects mod-scope (sandboxed) global environment
|
||||
|
||||
|
||||
------------------------------
|
||||
---- River Water Cauldron ----
|
||||
------------------------------
|
||||
|
||||
-- Consists of 3 levels: 1/3 filled, 2/3 filled, 3/3 filled
|
||||
-- Redstone comparator signal per level.
|
||||
-- river water texture
|
||||
-- yields empty cauldron item when mined (contents are lost).
|
||||
mcl_cauldrons.cauldron_river_water_1 = merge_tables(mcl_cauldrons.cauldron_empty,{
|
||||
description = S("Cauldron (1/3 River Water)"),
|
||||
_doc_items_create_entry = false,
|
||||
groups = {
|
||||
pickaxey = 1,
|
||||
not_in_creative_inventory = 1,
|
||||
cauldron = 1,
|
||||
cauldron_filled = 1,
|
||||
comparator_signal = 1,
|
||||
cauldron_river_water = 1,
|
||||
},
|
||||
node_box = mcl_cauldrons.cauldron_nodeboxes[1],
|
||||
tiles = {
|
||||
"(default_river_water_source_animated.png^[verticalframe:16:0)^mcl_cauldrons_cauldron_top.png",
|
||||
"mcl_cauldrons_cauldron_inner.png^mcl_cauldrons_cauldron_bottom.png",
|
||||
"mcl_cauldrons_cauldron_side.png"
|
||||
},
|
||||
drop = "mcl_cauldrons:cauldron",
|
||||
_cauldron_content = "river_water",
|
||||
})
|
||||
|
||||
-- river water cauldron, 2/3 filled
|
||||
mcl_cauldrons.cauldron_river_water_2 = merge_tables(mcl_cauldrons.cauldron_river_water_1, {
|
||||
description = S("Cauldron (2/3 River Water)"),
|
||||
groups = merge_tables(mcl_cauldrons.cauldron_river_water_1.groups, {
|
||||
cauldron_filled = 2,
|
||||
comparator_signal = 2,
|
||||
}),
|
||||
node_box = mcl_cauldrons.cauldron_nodeboxes[2],
|
||||
})
|
||||
|
||||
-- river water cauldron, 3/3 filled (full).
|
||||
mcl_cauldrons.cauldron_river_water_3 = merge_tables(mcl_cauldrons.cauldron_river_water_1, {
|
||||
description = S("Cauldron (3/3 River Water)"),
|
||||
groups = merge_tables(mcl_cauldrons.cauldron_river_water_1.groups, {
|
||||
cauldron_filled = 3,
|
||||
comparator_signal = 3,
|
||||
}),
|
||||
node_box = mcl_cauldrons.cauldron_nodeboxes[3],
|
||||
})
|
||||
|
||||
|
||||
mcl_cauldrons.register_cauldron_node("mcl_cauldrons:cauldron_river_water_1", mcl_cauldrons.cauldron_river_water_1, "mcl_cauldrons:cauldron")
|
||||
mcl_cauldrons.register_cauldron_node("mcl_cauldrons:cauldron_river_water_2", mcl_cauldrons.cauldron_river_water_2, "mcl_cauldrons:cauldron")
|
||||
mcl_cauldrons.register_cauldron_node("mcl_cauldrons:cauldron_river_water_3", mcl_cauldrons.cauldron_river_water_3, "mcl_cauldrons:cauldron")
|
|
@ -0,0 +1,62 @@
|
|||
-- Node definitions to implement Water Cauldron
|
||||
-- expects mod-scope (sandboxed) global environment
|
||||
|
||||
------------------------
|
||||
---- Water Cauldron ----
|
||||
------------------------
|
||||
|
||||
-- Consists of 3 levels: 1/3 filled, 2/3 filled, 3/3 filled
|
||||
-- Redstone comparator signal per level.
|
||||
-- water texture
|
||||
-- yields empty cauldron item when mined (contents are lost).
|
||||
mcl_cauldrons.cauldron_water_1 = merge_tables(mcl_cauldrons.cauldron_empty, {
|
||||
description = S("Cauldron (1/3 Water)"),
|
||||
_doc_items_create_entry = false,
|
||||
groups = {
|
||||
pickaxey = 1,
|
||||
not_in_creative_inventory = 1,
|
||||
cauldron = 1,
|
||||
cauldron_filled = 1,
|
||||
cauldron_water = 1,
|
||||
comparator_signal = 1
|
||||
},
|
||||
node_box = mcl_cauldrons.cauldron_nodeboxes[1],
|
||||
tiles = {
|
||||
"(default_water_source_animated.png^[verticalframe:16:0)^mcl_cauldrons_cauldron_top.png",
|
||||
"mcl_cauldrons_cauldron_inner.png^mcl_cauldrons_cauldron_bottom.png",
|
||||
"mcl_cauldrons_cauldron_side.png"
|
||||
},
|
||||
drop = "mcl_cauldrons:cauldron",
|
||||
_cauldron_content = "water",
|
||||
})
|
||||
|
||||
|
||||
-- TODO: Node definitions specify both groups.cauldron_<SUBSTANCE> and _cauldron_content=SUBSTANCE; feels almost redundant, maybe pick one?
|
||||
-- 1. using only groups.cauldron_<SUBSTANCE> may require lookup tables for all valid group keys to determine the substance they represent.
|
||||
-- 2. using only _cauldron_content would require constantly accessing the node definition table (minetest.registered_nodes) to determine cauldron content.
|
||||
|
||||
|
||||
-- water cauldron, fill level 2 (of 3); extends cauldron_water_1
|
||||
mcl_cauldrons.cauldron_water_2 = merge_tables(mcl_cauldrons.cauldron_water_1, {
|
||||
description = S("Cauldron (2/3 Water)"),
|
||||
groups = merge_tables(mcl_cauldrons.cauldron_water_1.groups, {
|
||||
cauldron_filled = 2,
|
||||
comparator_signal = 2,
|
||||
}),
|
||||
node_box = mcl_cauldrons.cauldron_nodeboxes[2],
|
||||
})
|
||||
|
||||
-- water cauldron, fill level 3 (of 3)/full, extends cauldron_water_1
|
||||
mcl_cauldrons.cauldron_water_3 = merge_tables(mcl_cauldrons.cauldron_water_1, {
|
||||
description = S("Cauldron (3/3 Water)"),
|
||||
groups = merge_tables(mcl_cauldrons.cauldron_water_1.groups, {
|
||||
cauldron_filled = 3,
|
||||
comparator_signal = 3,
|
||||
}),
|
||||
node_box = mcl_cauldrons.cauldron_nodeboxes[3],
|
||||
})
|
||||
|
||||
-- keep registration code fully expanded to help with search and code tools.
|
||||
mcl_cauldrons.register_cauldron_node("mcl_cauldrons:cauldron_water_1", mcl_cauldrons.cauldron_water_1, "mcl_cauldrons:cauldron")
|
||||
mcl_cauldrons.register_cauldron_node("mcl_cauldrons:cauldron_water_2", mcl_cauldrons.cauldron_water_2, "mcl_cauldrons:cauldron")
|
||||
mcl_cauldrons.register_cauldron_node("mcl_cauldrons:cauldron_water_3", mcl_cauldrons.cauldron_water_3, "mcl_cauldrons:cauldron")
|
|
@ -1,9 +1,72 @@
|
|||
local S = minetest.get_translator("mcl_cauldron")
|
||||
local modpath = minetest.get_modpath(minetest.get_current_modname())
|
||||
local modname = minetest.get_current_modname()
|
||||
local modpath = minetest.get_modpath(modname)
|
||||
local mclx_core = minetest.get_modpath("mclx_core")
|
||||
local has_doc = minetest.get_modpath("doc")
|
||||
|
||||
mcl_cauldrons = {}
|
||||
-- Cauldron mod, adds cauldrons.
|
||||
|
||||
mcl_cauldrons = {}
|
||||
|
||||
|
||||
-- set up a mod-scope environment.
|
||||
local _MODENV = {
|
||||
S = S,
|
||||
modname = modname,
|
||||
modpath = modpath,
|
||||
mclx_core = mclx_core,
|
||||
has_doc = has_doc,
|
||||
}
|
||||
-- chain to global.
|
||||
_MODENV._MODENV = _MODENV
|
||||
setmetatable(_MODENV, { __index = _G })
|
||||
|
||||
|
||||
--- execute subcomponents in context of this mod-scope environment.
|
||||
--- (anything defined global-style stays in this containment environment, without polluting the "true" global environment; that said, true-global still accessible explicitly through _G._G)
|
||||
--- N.B. "mcl_cauldrons" has already been defined (though empty) in
|
||||
--- the "true-global" environment, so modifying keys in mcl_cauldrons
|
||||
--- still affect the "true-global" mcl_cauldrons.
|
||||
|
||||
if setfenv then
|
||||
-- Lua 5.1, environment with setfenv().
|
||||
setfenv(1, _MODENV)
|
||||
|
||||
function dosubfile (submodpath)
|
||||
local submodule, err
|
||||
submodule, err = loadfile(modpath .. "/" .. submodpath)
|
||||
if err then
|
||||
print(err)
|
||||
print(debug.traceback())
|
||||
-- error(err)
|
||||
error()
|
||||
end
|
||||
-- submodule = loadfile(modpath .. "/" .. submodpath)
|
||||
setfenv(submodule, _MODENV)
|
||||
submodule()
|
||||
end
|
||||
else
|
||||
-- Lua post-5.1, environment as argument.
|
||||
_ENV = _MODENV
|
||||
function dosubfile (submodpath)
|
||||
return dofile(modpath .. "/" .. submodpath, "bt", _MODENV)
|
||||
end
|
||||
end
|
||||
|
||||
--[[
|
||||
-- utilities and preset values used by API.
|
||||
dofile(modpath.."/utils.lua")
|
||||
-- API definition.
|
||||
dofile(modpath.."/api.lua")
|
||||
-- standard set of cauldrons.
|
||||
dofile(modpath.."/cauldrons.lua")
|
||||
-- more registration stuff.
|
||||
dofile(modpath.."/register.lua")
|
||||
--]]
|
||||
|
||||
dosubfile("utils.lua")
|
||||
dosubfile("api.lua")
|
||||
dosubfile("cauldron.lua")
|
||||
|
||||
|
||||
-- _ENV automatically goes out of scope at the end of this chunk/file.
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
local S = minetest.get_translator(minetest.get_current_modname())
|
||||
|
||||
-- All registration activities
|
||||
|
||||
--[[
|
||||
mcl_cauldrons.register_cauldron_type({
|
||||
name = "water",
|
||||
bucket = "mcl_buckets:bucket_water",
|
||||
|
@ -7,11 +10,20 @@ mcl_cauldrons.register_cauldron_type({
|
|||
desc = S("Cauldron (%s/3 Water)"),
|
||||
texture = "default_water_source_animated.png"
|
||||
})
|
||||
--]]
|
||||
|
||||
mcl_cauldrons.register_cauldron_node("mcl_cauldrons:cauldron", mcl_cauldrons.cauldron_empty)
|
||||
mcl_cauldrons.register_cauldron_node("mcl_cauldrons:cauldron_water_1", mcl_cauldrons.cauldron_water_1)
|
||||
mcl_cauldrons.register_cauldron_node("mcl_cauldrons:cauldron_water_2", mcl_cauldrons.cauldron_water_2)
|
||||
mcl_cauldrons.register_cauldron_node("mcl_cauldrons:cauldron_water_3", mcl_cauldrons.cauldron_water_3)
|
||||
|
||||
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)
|
||||
mcl_cauldrons.register_cauldron_node("mcl_cauldrons:cauldron_river_water_1", mcl_cauldrons.cauldron_river_water_1)
|
||||
mcl_cauldrons.register_cauldron_node("mcl_cauldrons:cauldron_river_water_2", mcl_cauldrons.cauldron_river_water_2)
|
||||
mcl_cauldrons.register_cauldron_node("mcl_cauldrons:cauldron_river_water_3", mcl_cauldrons.cauldron_river_water_3)
|
||||
end
|
||||
|
||||
minetest.register_craft({
|
||||
|
@ -40,9 +52,26 @@ minetest.register_abm({
|
|||
end
|
||||
})
|
||||
|
||||
--[[
|
||||
for i = 1, 3 do --Backward compatibility
|
||||
minetest.register_alias("mcl_cauldrons:cauldron_"..i, "mcl_cauldrons:cauldron_water_"..i)
|
||||
end
|
||||
for i = 1, 3 do
|
||||
minetest.register_alias("mcl_cauldrons:cauldron_"..i.."r", "mcl_cauldrons:cauldron_river_water_"..i)
|
||||
end
|
||||
end
|
||||
--]]
|
||||
|
||||
-- Backwards compatibility.
|
||||
local aliases = {
|
||||
-- key=old/deprecated nodename, value=current nodename
|
||||
["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 old_nodename, current_nodename in pairs(aliases) do
|
||||
minetest.register_alias(old_nodename, current_nodename)
|
||||
end
|
||||
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
local S = minetest.get_translator(minetest.get_current_modname())
|
||||
|
||||
-- utility functions and preset values used by mcl_cauldron definitions.
|
||||
|
||||
--[[
|
||||
-- Convenience function because the cauldron nodeboxes are very similar
|
||||
local create_cauldron_nodebox = function(water_level)
|
||||
local floor_y
|
||||
|
@ -36,7 +39,9 @@ mcl_cauldrons.cauldron_nodeboxes = {}
|
|||
for w=0,3 do
|
||||
mcl_cauldrons.cauldron_nodeboxes[w] = create_cauldron_nodebox(w)
|
||||
end
|
||||
--]]
|
||||
|
||||
--[[
|
||||
-- Empty cauldron
|
||||
minetest.register_node("mcl_cauldrons:cauldron", {
|
||||
description = S("Cauldron"),
|
||||
|
@ -60,4 +65,5 @@ minetest.register_node("mcl_cauldrons:cauldron", {
|
|||
sounds = mcl_sounds.node_sound_metal_defaults(),
|
||||
_mcl_hardness = 2,
|
||||
_mcl_blast_resistance = 2,
|
||||
})
|
||||
})
|
||||
--]]
|
||||
|
|
|
@ -40,6 +40,80 @@ minetest.register_craft({
|
|||
recipe = { "mcl_mushrooms:mushroom_brown", "mcl_core:sugar", "mcl_mobitems:spider_eye" },
|
||||
})
|
||||
|
||||
|
||||
local function take_from_cauldron (cauldron, itemstack, placer)
|
||||
local sounds = mcl_sounds.node_sound_metal_defaults() -- TODO: should come from declarative object
|
||||
-- check cauldron limits.
|
||||
local new_bottlename
|
||||
if cauldron:get_level("water") then
|
||||
-- has water, try to take water.
|
||||
if cauldron:drain_levels("water", cauldron.BOTTLEFUL) then
|
||||
cauldron:update_node()
|
||||
minetest.sound_play("mcl_potions_bottle_fill", {pos=cauldron.pos, gain=0.5, max_hear_range=16}, true)
|
||||
new_bottlename = "mcl_potions:water"
|
||||
end
|
||||
end
|
||||
if new_bottlename then
|
||||
-- byproduct of draining cauldron.
|
||||
local new_bottle = ItemStack({name=new_bottlename})
|
||||
local inv = placer:get_inventory()
|
||||
if minetest.is_creative_enabled(placer:get_player_name()) then
|
||||
-- creative mode: get for free
|
||||
if not inv:contains_item("main", new_bottle) then
|
||||
inv:add_item("main", new_bottle)
|
||||
end
|
||||
else
|
||||
-- survival mode
|
||||
if inv:room_for_item("main", new_bottle) then
|
||||
itemstack:take_item()
|
||||
inv:add_item("main", new_bottle)
|
||||
else
|
||||
minetest.add_item(placer:get_pos(), new_bottle)
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function give_to_cauldron (cauldron, itemstack, placer, substance)
|
||||
if substance == nil then
|
||||
return false
|
||||
end
|
||||
local sounds = mcl_sounds.node_sound_metal_defaults() -- TODO: should come from declarative object
|
||||
-- check cauldron limits.
|
||||
local new_bottlename
|
||||
if cauldron:get_level(substance) <= (cauldron:get_capacity(substance) - cauldron.BOTTLEFUL) then
|
||||
-- sufficiently low level, add.
|
||||
-- overwrites old content (old contents are lost).
|
||||
if cauldron:fill_levels(substance, cauldron.BOTTLEFUL) then
|
||||
cauldron:update_node()
|
||||
minetest.sound_play("mcl_potions_bottle_pour", {pos=cauldron.pos, gain=0.5, max_hear_range=16}, true)
|
||||
new_bottlename = "mcl_potions:glass_bottle"
|
||||
end
|
||||
end
|
||||
if new_bottlename then
|
||||
-- byproduct of filling cauldron.
|
||||
local new_bottle = ItemStack({name=new_bottlename})
|
||||
local inv = placer:get_inventory()
|
||||
if minetest.is_creative_enabled(placer:get_player_name()) then
|
||||
-- creative mode: get for free
|
||||
if not inv:contains_item("main", new_bottle) then
|
||||
inv:add_item("main", new_bottle)
|
||||
end
|
||||
else
|
||||
-- survival mode
|
||||
if inv:room_for_item("main", new_bottle) then
|
||||
itemstack:take_item()
|
||||
inv:add_item("main", new_bottle)
|
||||
else
|
||||
minetest.add_item(placer:get_pos(), new_bottle)
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
minetest.register_craftitem("mcl_potions:glass_bottle", {
|
||||
description = S("Glass Bottle"),
|
||||
_tt_help = S("Liquid container"),
|
||||
|
@ -65,12 +139,18 @@ minetest.register_craftitem("mcl_potions:glass_bottle", {
|
|||
local get_water = false
|
||||
--local from_liquid_source = false
|
||||
local river_water = false
|
||||
local from_cauldron = mcl_cauldrons.get_cauldron(pointed_thing.under)
|
||||
if from_cauldron and from_cauldron:is_empty() then
|
||||
-- cannot take from empty cauldron.
|
||||
from_cauldron = nil
|
||||
end
|
||||
if def and def.groups and def.groups.water and def.liquidtype == "source" then
|
||||
-- Water source
|
||||
get_water = true
|
||||
--from_liquid_source = true
|
||||
river_water = node.name == "mclx_core:river_water_source"
|
||||
-- Or reduce water level of cauldron by 1
|
||||
--[[
|
||||
elseif mcl_cauldrons.is_cauldron(node.name) then
|
||||
local pname = placer:get_player_name()
|
||||
if minetest.is_protected(pointed_thing.under, pname) then
|
||||
|
@ -78,6 +158,18 @@ minetest.register_craftitem("mcl_potions:glass_bottle", {
|
|||
return itemstack
|
||||
end
|
||||
mcl_cauldrons.take_small_cauldron(pointed_thing.under, itemstack, placer, {dug = "mcl_potions_bottle_fill"})
|
||||
--]]
|
||||
elseif from_cauldron then
|
||||
if from_cauldron:get_level("water") then
|
||||
-- take bottle of water.
|
||||
local pname = placer:get_player_name()
|
||||
if minetest.is_protected(pointed_thing.under, pname) then
|
||||
minetest.record_protection_violation(pointed_thing.under, pname)
|
||||
return itemstack
|
||||
end
|
||||
|
||||
take_from_cauldron(from_cauldron, itemstack, placer)
|
||||
end
|
||||
end
|
||||
end
|
||||
return itemstack
|
||||
|
@ -125,6 +217,7 @@ minetest.register_craftitem("mcl_potions:water", {
|
|||
end
|
||||
end
|
||||
|
||||
--[[
|
||||
local cauldron = fill_cauldron(node.name, "mcl_core:water_source")
|
||||
if cauldron then
|
||||
local pname = placer:get_player_name()
|
||||
|
@ -141,6 +234,18 @@ minetest.register_craftitem("mcl_potions:water", {
|
|||
return "mcl_potions:glass_bottle"
|
||||
end
|
||||
end
|
||||
--]]
|
||||
local to_cauldron = mcl_cauldrons.get_cauldron(pointed_thing.under)
|
||||
-- apply water bottle to empty or water cauldron
|
||||
-- anything else, replace content.
|
||||
if to_cauldron then
|
||||
local pname = placer:get_player_name()
|
||||
if minetest.is_protected(pointed_thing.under, pname) then
|
||||
minetest.record_protection_violation(pointed_thing.under, pname)
|
||||
return itemstack
|
||||
end
|
||||
give_to_cauldron(to_cauldron, itemstack, placer, "water")
|
||||
end
|
||||
end
|
||||
|
||||
-- Drink the water by default
|
||||
|
@ -385,4 +490,5 @@ mcl_wip.register_wip_item("mcl_potions:night_vision_plus_splash")
|
|||
mcl_wip.register_wip_item("mcl_potions:night_vision_lingering")
|
||||
mcl_wip.register_wip_item("mcl_potions:night_vision_plus_lingering")
|
||||
mcl_wip.register_wip_item("mcl_potions:night_vision_arrow")
|
||||
mcl_wip.register_wip_item("mcl_potions:night_vision_plus_arrow")
|
||||
mcl_wip.register_wip_item("mcl_potions:night_vision_plus_arrow")
|
||||
|
||||
|
|
Loading…
Reference in New Issue