melterns/multifurnace/faucet.lua
2019-03-25 19:31:12 +02:00

187 lines
4.8 KiB
Lua

-- Faucet is a simple liquid transfer node
local FAUCET_PER_SECOND = 122
local function update_timer (pos)
local t = minetest.get_node_timer(pos)
if not t:is_started() then
t:start(1.0)
end
end
local function faucet_flow (pos, meta)
local angled = minetest.get_node(pos)
local back = vector.add(pos, minetest.facedir_to_dir(angled.param2))
local backnode = minetest.get_node(back)
local backreg = minetest.registered_nodes[backnode.name]
if not backreg.node_io_can_take_liquid or not backreg.node_io_can_take_liquid(back, backnode, "front")
or not backreg.node_io_take_liquid then
return false
end
local stack
if backreg.node_io_get_liquid_stack then
stack = backreg.node_io_get_liquid_stack(back, backnode, "front", 1)
end
if not stack or stack:is_empty() then
return false
end
return stack:get_name(), stack:get_count(), back
end
local function faucet_activate (pos)
local meta = minetest.get_meta(pos)
local source, amount, bhind = faucet_flow(pos, meta)
if meta:get_string("flowing") ~= "" then return false end
if not source or amount == 0 then return end
local e = minetest.add_entity(pos, "multifurnace:faucet_flow")
e:get_luaentity():set_faucet(pos)
e:get_luaentity():set_source(source)
meta:set_string("flowing", source)
meta:set_int("flowing_capacity", amount)
update_timer(pos)
end
local function faucet_timer (pos, elapsed)
local refresh = false
local meta = minetest.get_meta(pos)
local liquid = meta:get_string("flowing")
local source, amount, bhind = faucet_flow(pos, meta)
while true do
if liquid == "" then break end
if source ~= liquid or amount <= 0 then
liquid = ""
break
end
local bhindnode = minetest.get_node(bhind)
local bhindreg = minetest.registered_nodes[bhindnode.name]
local target = vector.subtract(pos, {x=0,y=1,z=0})
local tnode = minetest.get_node(target)
local treg = minetest.registered_nodes[tnode.name]
if not treg.node_io_can_put_liquid or not treg.node_io_can_put_liquid(target, tnode, "top")
or not treg.node_io_room_for_liquid then
liquid = ""
break
end
local flowcap = amount
if flowcap > FAUCET_PER_SECOND then
flowcap = FAUCET_PER_SECOND
end
local room = treg.node_io_room_for_liquid(target, tnode, "top", liquid, flowcap)
if room > 0 and treg.node_io_put_liquid then
local over = treg.node_io_put_liquid(target, tnode, "top", nil, liquid, room)
if treg.on_timer then
update_timer(target)
end
else
liquid = ""
break
end
bhindreg.node_io_take_liquid(bhind, bhindnode, "front", nil, source, room)
if bhindreg.on_timer then
update_timer(bhind)
end
refresh = true
break
end
meta:set_string("flowing", liquid)
return refresh
end
minetest.register_node("multifurnace:faucet", {
description = "Multifurnace Faucet",
tiles = {"metal_melter_heatbrick.png"},
groups = {cracky = 3, multifurnace_accessory = 1},
drawtype = "nodebox",
node_box = {
type = "fixed",
fixed = {
{-0.1875, -0.1875, 0.1250, 0.1875, -0.1250, 0.5000},
{-0.1875, -0.1250, 0.1250, -0.1250, 0.06250, 0.5000},
{0.1250, -0.1250, 0.1250, 0.1875, 0.06250, 0.5000}
}
},
paramtype = "light",
paramtype2 = "facedir",
is_ground_content = false,
on_rightclick = faucet_activate,
on_timer = faucet_timer,
})
-- Flow entity
minetest.register_entity("multifurnace:faucet_flow", {
initial_properties = {
physical = false,
collide_with_objects = false,
visual = "mesh",
mesh = "multifurnace_faucet_flow.obj",
visual_size = {x = 5, y = 5},
textures = {},
backface_culling = true,
pointable = false,
static_save = false,
},
faucet = nil,
source = "",
timer = 0,
set_faucet = function (self, faucet)
self.faucet = faucet
-- Set correct orientation in regards to the faucet
local node = minetest.get_node(faucet)
local orient = minetest.facedir_to_dir(node.param2)
orient = vector.multiply(orient, -1)
local angle = minetest.dir_to_yaw(orient)
self.object:set_yaw(angle)
end,
set_source = function (self, source)
self.source = source
-- Set appropriate fluid texture
local tiles = minetest.registered_nodes[source]
if not tiles.liquid_alternative_flowing then return end
local flowing = minetest.registered_nodes[tiles.liquid_alternative_flowing]
if not flowing.tiles or type(flowing.tiles[1]) ~= "string" then return end
self.object:set_properties({textures = {
flowing.tiles[1]
}})
end,
on_step = function (self, dt)
self.timer = self.timer + 1
-- Remove self when the faucet is destroyed or is no longer marked as flowing
if self.timer >= 10 then
local node = minetest.get_node(self.faucet)
if not node or node.name ~= "multifurnace:faucet" then
self.object:remove()
return
end
local meta = minetest.get_meta(self.faucet)
if meta:get_string("flowing") ~= self.source then
self.object:remove()
return
end
self.timer = 0
end
end
})