forked from VoxeLibre/VoxeLibre
Adjust callbacks to operate from on_rightclick (delegated from potions and buckets).
This commit is contained in:
parent
91fe85fd1b
commit
05a9968081
|
@ -92,11 +92,11 @@ function mcl_cauldrons.empty_cauldron_on_drain(node, change_levels, substance)
|
|||
-- no change.
|
||||
return nil
|
||||
end
|
||||
if (substance and not mcl_cauldrons.has_substance(node, substance)) then
|
||||
if (substance and not mcl_cauldrons.node_has_substance(node, substance)) then
|
||||
-- different substance, cannot drain.
|
||||
return nil
|
||||
end
|
||||
local old_level = mcl_cauldrons.get_level(node)
|
||||
local old_level = mcl_cauldrons.node_get_level(node)
|
||||
local whole, fraction = math.modf(change_levels)
|
||||
local new_level
|
||||
if fraction > 0 then
|
||||
|
@ -112,10 +112,305 @@ function mcl_cauldrons.empty_cauldron_on_drain(node, change_levels, substance)
|
|||
new_level = old_level - whole
|
||||
-- clamp 0 through 3 inclusive.
|
||||
new_level = math.max(0, math.min(new_level, 3))
|
||||
local newnode = mcl_cauldrons.set_level(node, new_level, substance)
|
||||
local newnode = mcl_cauldrons.node_set_level(node, new_level, substance)
|
||||
return newnode
|
||||
end
|
||||
|
||||
|
||||
-- test for membership in list (styled after R7RS)
|
||||
local function member(obj, lis)
|
||||
for i, v in ipairs(lis) do
|
||||
if v == obj then return true end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
-- Predicate: item stack content is a bottle (potion).
|
||||
local function is_a_bottle(itemstack)
|
||||
-- determinants for bottle not yet finalized.
|
||||
local itemdef = itemstack:get_definition()
|
||||
if minetest.get_item_group(itemdef, "brewitem") ~= 0 then
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- Predicate: item stack content is glass (empty) bottle.
|
||||
local function is_bottle_empty(itemstack)
|
||||
if not is_a_bottle(itemstack) then return false end
|
||||
-- Compare to item name; I don't like this (would prefer groups property or other itemdef property), but it works for now.
|
||||
local BY_NAME = {
|
||||
"mcl_potions:glass_bottle",
|
||||
}
|
||||
if member(itemstack:get_name(), BY_NAME) then return true end
|
||||
end
|
||||
|
||||
-- Predicate: item stack content is a water bottle/potion.
|
||||
local function is_bottle_water(itemstack)
|
||||
if not is_a_bottle(itemstack) then return false end
|
||||
-- works for now; prefer group/itemdef property.
|
||||
local BY_NAME = {
|
||||
"mcl_potions:water",
|
||||
}
|
||||
if member(itemstack:get_name(), BY_NAME) then return true end
|
||||
end
|
||||
|
||||
-- Predicate: item stack content is a river water bottle.
|
||||
local function is_bottle_river_water(itemstack)
|
||||
if not is_a_bottle(itemstack) then return false end
|
||||
-- works for now; prefer group/itemdef property.
|
||||
local BY_NAME = {
|
||||
"mcl_potions:river_water",
|
||||
}
|
||||
if member(itemstack:get_name(), BY_NAME) then return true end
|
||||
end
|
||||
|
||||
-- Predicate: item definition is a bucket.
|
||||
local function is_a_bucket(itemstack)
|
||||
local itemdef = itemstack:get_definition()
|
||||
if (minetest.get_item_group(itemdef, "bucket") ~= 0) then return true end
|
||||
-- other tests?
|
||||
return false
|
||||
end
|
||||
|
||||
-- Predicate: item definition is a bucket of water.
|
||||
local function is_bucket_water(itemdef)
|
||||
local BY_NAME = {
|
||||
"mcl_buckets:bucket_water",
|
||||
}
|
||||
if member(itemstack:get_name(), BY_NAME) then return true end
|
||||
end
|
||||
|
||||
-- Predicate: item definition is a bucket of river water.
|
||||
local function is_bucket_river_water(itemdef)
|
||||
local BY_NAME = {
|
||||
"mcl_buckets:bucket_water",
|
||||
}
|
||||
if member(itemstack:get_name(), BY_NAME) then return true end
|
||||
end
|
||||
|
||||
-- Predicate: item definition is a banner (washable).
|
||||
local function is_a_banner(itemdef)
|
||||
end
|
||||
|
||||
|
||||
-- Empty Bucket on Empty Cauldron - accomplish nothing.
|
||||
function mcl_cauldrons.empty_cauldron_on_apply_bucket_empty(pos, node, user, itemstack)
|
||||
return false
|
||||
end
|
||||
|
||||
-- Water Bucket on Empty Cauldron - possibly fill with water.
|
||||
function mcl_cauldrons.empty_cauldron_on_apply_bucket_water(pos, node, user, itemstack)
|
||||
local newnode = mcl_cauldrons.fill_levels(node, mcl_cauldrons.BUCKET_FILL_LEVELS, "cauldron_water")
|
||||
if newnode ~= node then
|
||||
minetest.set_node(pos, node)
|
||||
end
|
||||
end
|
||||
|
||||
function mcl_cauldrons.empty_cauldron_on_apply_bucket_river_water(pos, node, user, itemstack)
|
||||
end
|
||||
|
||||
-- apply an itemstack to Empty Cauldron.
|
||||
function mcl_cauldrons.empty_cauldron_on_apply_item(pos, node, user, itemstack)
|
||||
local DELEGATES = {
|
||||
[mcl_cauldrons.is_a_bucket]=empty_cauldron_apply_bucket,
|
||||
[mcl_cauldrons.is_a_bottle]=empty_cauldron_apply_bottle,
|
||||
}
|
||||
for predicate, handler in pairs(DELEGATES) do
|
||||
if predicate(itemstack) then
|
||||
return handler(pos, node, user, itemstack)
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
local function extends(parent_class, child_class)
|
||||
if child_class == nil then child_class = {} end
|
||||
child_class.__index = parent_class
|
||||
setmetatable(child_class, child_class)
|
||||
return child_class
|
||||
end
|
||||
|
||||
|
||||
|
||||
mcl_cauldrons.CauldronInteractable = {
|
||||
-- check if a particular ItemStack may be applied to cauldron.
|
||||
handles_item = function(itemstack)
|
||||
return false
|
||||
end,
|
||||
-- table, key is a predicate function(itemstack), value is function(pos, node, user, itemstack).
|
||||
itemstack_handlers = {
|
||||
},
|
||||
apply_item = function(pos, node, user, itemstack)
|
||||
end,
|
||||
}
|
||||
|
||||
|
||||
-- Generalized vessels interaction with Cauldron (buckets, bottles).
|
||||
-- * May change cauldron state (substance+fill_level; fill/drain)
|
||||
-- * Exchanges one vessel item for another vessel item when applying to cauldron.
|
||||
mcl_cauldrons.Vessel = extends(mcl_cauldrons.CauldronInteractable, {
|
||||
__index = mcl_cauldrons.CauldronInteractable,
|
||||
-- check that item is a member of specified group (minetest.item_get_group).
|
||||
_groups_membership = {
|
||||
},
|
||||
-- common one-for-one exchange: put new_node at pos, and in exchange take 1 from itemstack, and give 1 of new_item to user.
|
||||
common_exchange = function(pos, new_node, user, itemstack, new_item)
|
||||
if new_node ~= nil then
|
||||
minetest.set_node(pos, new_node)
|
||||
end
|
||||
if new_item ~= nil then
|
||||
local new_itemstack = ItemStack(new_item)
|
||||
if minetest.is_creative_enabled(user:get_player_name()) then
|
||||
-- creative inventory: add new_item 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
|
||||
end,
|
||||
handles_item = function(itemstack)
|
||||
for i, v in ipairs(self._groups_membership) do
|
||||
if minetest.get_item_group(itemstack:get_name(), v) ~= 0 then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
|
||||
-- Bucket(-like) interactions with Cauldron.
|
||||
mcl_cauldrons.Bucket = extends(mcl_cauldrons.Vessel, {
|
||||
_groups_membership = {
|
||||
"bucket",
|
||||
},
|
||||
-- internal use, get a specific Bucket type fitting itemstack.
|
||||
_get_specific = function(itemstack)
|
||||
-- introspect for table members with {predicate,canonical_item} keys.
|
||||
for scan_name, scan_specific in pairs(self) do
|
||||
if type(scan_specific) == table and scan_specific.predicate and scan.canonical_item then
|
||||
if scan_specific.predicate(itemstack) then
|
||||
return scan_specific
|
||||
end
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end,
|
||||
})
|
||||
|
||||
mcl_cauldrons.Bucket.Empty = {
|
||||
-- returns true if itemstack corresponds to the item being handled (conditional before running apply()).
|
||||
predicate = function(itemstack)
|
||||
if member(itemstack:get_name(), {"mcl_buckets:bucket"}) then return true end
|
||||
end,
|
||||
delegate_apply = function(interactable, node, itemdef)
|
||||
-- empty bucket may turn into a something bucket.
|
||||
for scan_field, scan_specific in pairs(interactable) do
|
||||
if scan_specific.cauldron_substance then
|
||||
-- non-empty bucket
|
||||
local newnode = mcl_cauldrons.node_drain_levels(node, mcl_cauldrons.BUCKET_FILL_LEVELS, scan_specific.cauldron_substance)
|
||||
if newnode ~= node then
|
||||
-- cauldron due to change; get exchanged item.
|
||||
local newitem = scan_specific.canonical_item
|
||||
return newnode, newitem
|
||||
end
|
||||
end
|
||||
end
|
||||
end,
|
||||
canonical_item = "mcl_buckets:bucket",
|
||||
}
|
||||
|
||||
-- Bucket of Water vs Cauldron
|
||||
mcl_cauldrons.Bucket.Water = {
|
||||
predicate = function(itemstack)
|
||||
-- Compare to item name; I don't like this (would prefer groups property or other itemdef property), but it works for now.
|
||||
if member(itemstack:get_name(), {"mcl_buckets:bucket_water"}) then return true end
|
||||
end,
|
||||
delegate_apply = function(interactable, node, itemdef)
|
||||
-- water bucket turns into empty bucket.
|
||||
local newnode = mcl_cauldrons.node_fill_levels(node, mcl_cauldrons.BUCKET_FILL_LEVELS, self.cauldron_substance)
|
||||
-- exchange bucket even if cauldron didn't change.
|
||||
local newitem = interactable.Empty.canonical_item
|
||||
return newnode, newitem
|
||||
end,
|
||||
cauldron_substance = "cauldron_water",
|
||||
canonical_item = "mcl_buckets:bucket_water",
|
||||
}
|
||||
|
||||
-- Bucket of River Water vs Cauldron
|
||||
mcl_cauldrons.Bucket.RiverWater = extends(mcl_cauldrons.Bucket.Water, {
|
||||
predicate = function(itemstack)
|
||||
-- would prefer group/itemdef properties instead of name comparison.
|
||||
if member(itemstack:get_name(), {"mcl_buckets:bucket_river_water"}) then return true end
|
||||
end,
|
||||
-- inherit delegate_apply()
|
||||
cauldron_substance = "cauldron_river_water",
|
||||
canonical_item = "mcl_buckets:bucket_river_water",
|
||||
})
|
||||
|
||||
function mcl_cauldrons.Bucket:apply(pos, node, user, itemstack)
|
||||
local specific = self:get_specific(itemstack)
|
||||
if specific == nil then return end
|
||||
local newnode, newitem = specific:delegate_apply(self, node, itemstack:get_definition())
|
||||
self:common_exchange(pos, newnode, user, itemstack, newitem)
|
||||
end
|
||||
|
||||
function mcl_cauldrons.Bucket:handles_item(itemstack)
|
||||
return (self:_get_specific(itemstack) ~= nil)
|
||||
end
|
||||
|
||||
|
||||
-- Bottle interactions with Cauldron.
|
||||
mcl_cauldrons.Bottle = {
|
||||
_group_membership = {
|
||||
"potion",
|
||||
}
|
||||
}
|
||||
setmetatable(mcl_cauldrons.Bottle, mcl_cauldrons.Bottle)
|
||||
|
||||
|
||||
mcl_cauldrons.EmptyCauldron = {
|
||||
-- registry of item(proxie)s that may interact with cauldron.
|
||||
known_items = {
|
||||
mcl_cauldrons.Bucket,
|
||||
mcl_cauldrons.Bottle,
|
||||
},
|
||||
apply_item = function(pos, node, user, itemstack)
|
||||
-- list of actions to carry out as a result of applying item.
|
||||
-- allows for rollback/cancelling in case of errors or exceptions.
|
||||
local plan = {}
|
||||
for _, item_handler in ipairs(self.known_items) do
|
||||
if item_handler:handles_item(itemstack) then
|
||||
item_handler:apply(pos, node, user, itemstack)
|
||||
end
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
|
||||
-- Empty cauldron
|
||||
mcl_cauldrons.register_cauldron_node("mcl_cauldrons:cauldron", {
|
||||
description = S("Cauldron"),
|
||||
|
@ -140,11 +435,24 @@ mcl_cauldrons.register_cauldron_node("mcl_cauldrons:cauldron", {
|
|||
_mcl_hardness = 2,
|
||||
_mcl_blast_resistance = 2,
|
||||
|
||||
--[[
|
||||
_mcl_on_fill = function(node, change_levels, substance)
|
||||
return mcl_cauldrons.empty_cauldron_on_fill(node, change_levels, substance)
|
||||
return mcl_cauldrons.do_empty_cauldron_on_fill(node, change_levels, substance)
|
||||
end,
|
||||
_mcl_on_drain = function(node, change_levels, substance)
|
||||
return mcl_cauldrons.empty_cauldron_on_drain(node, change_levels, substance)
|
||||
return mcl_cauldrons.do_empty_cauldron_on_drain(node, change_levels, substance)
|
||||
end,
|
||||
_mcl_on_apply_item = function(node, vessel_def)
|
||||
return mcl_cauldrons.do_empty_cauldron_apply_item(node, bucket_def)
|
||||
end,
|
||||
]]
|
||||
-- on right-click with an item.
|
||||
_mcl_on_right_click = function(place_pos, node, user, itemstack)
|
||||
return EmptyCauldron:apply_item(place_pos, node, user, itemstack)
|
||||
end,
|
||||
on_rightclick = function(place_pos, node, user, itemstack)
|
||||
print("ON_RIGHTCLICK", itemstack:get_name())
|
||||
return mcl_cauldrons:EmptyCauldron.apply_item(place_pos, node, user, itemstack)
|
||||
end,
|
||||
})
|
||||
|
||||
|
@ -251,7 +559,7 @@ minetest.register_abm({
|
|||
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.drain_levels(node, 1, "cauldron_water")
|
||||
local newnode = mcl_cauldrons.node_drain_levels(node, 1, "cauldron_water")
|
||||
if node ~= newnode then
|
||||
-- extinguishing requires 1 level of water from cauldron.
|
||||
minetest.swap_node(pos, newnode)
|
||||
|
|
Loading…
Reference in New Issue