This repository has been archived on 2019-06-10. You can view files and clone it, but cannot push or open issues or pull requests.
scriptblocks/grate.lua

196 lines
5.9 KiB
Lua

minetest.register_node("rmod:grate", {
description = "Grate",
tiles = {"rmod_grate.png"},
groups = {oddly_breakable_by_hand = 1},
use_texture_alpha = true,
drawtype = "glasslike",
paramtype = "light",
})
local function get_level(node, def)
local level = node.param2 % 16
if level > 8 then level = level - 8 end
if def and def.liquidtype == "source" then level = 8 end -- Ooh, this node is a SOURCE! MAX LEVEL!
if def and def.liquidtype ~= "flowing" and def.liquidtype ~= "source" then
level = def.floodable and 0 or 8 -- Okay, the node isn't liquid. But we can still determine whether it contains undisplaceable matter.
end
if not def then level = 8 end
return level
end
local function get_variables(pos)
local node = minetest.get_node(pos)
local name
if node then name = node.name else return end
local def = minetest.registered_nodes[name]
local level = get_level(node, def)
return node, name, def, level
end
local function calculate_level(pos)
return ({get_variables(pos)})[4]
end
local function attempt_flow_to(pos1, pos2, dec)
-- Try flowing from pos1 to pos2.
local node1, name1, def1, level1 = get_variables(pos1)
-- Flowing1 is the node we may or may not eventually place.
local flowing1 = def1.liquid_alternative_flowing
local node2, name2, def2, level2 = get_variables(pos2)
if def1.liquidtype ~= "source" and def1.liquidtype ~= "flowing" then return end
if not flowing1 then return end -- node might not be a liquid.
-- If we're flowing down, gravity is most likely going to aid.
-- Therefore, we should set the values accordingly.
if pos2.y < pos1.y then
level1 = 8 + dec
if def2.liquidtype == "flowing" then
level2 = 0
dec = 0
end
-- Opposite reasoning of above.
elseif pos2.y > pos1.y then return end
-- When water flows normally, it slowly decreases as it spreads outwards.
-- Dec is the variable applied to the originating liquid's level, which
-- the resulting output flow is decreased by.
-- Usually this value is 2, but I'm allowing for customization.
if level1 - dec <= level2 then return end
if level1 - dec < 0 then return end
minetest.set_node(pos2, {
name = flowing1,
param1 = pos1.param1,
param2 = level1 - dec
})
return true
end
local function grate_step(pos, offset)
local pos1 = vector.add(pos, offset)
if not attempt_flow_to(pos1, vector.subtract(pos, {x=0,y=1,z=0}), 2) then -- If we can't flow below...
local left_offset = {x = offset.z, y = 0, z = -offset.x}
local right_offset = {x = -offset.z, y = 0, z = offset.x}
attempt_flow_to(pos1, vector.subtract(pos, offset), 2) -- Try flowing forward.
attempt_flow_to(pos1, vector.add(pos, left_offset), 2) -- Try flowing left.
attempt_flow_to(pos1, vector.add(pos, right_offset), 2) -- And try flowing right.
end
--[[local neigh = vector.add(pos, offset)
local neigh_node, neigh_name, neigh_def, level = get_variables(neigh)
if not neigh_def then return end -- Unknown nodes can't flow.
if neigh_def.liquidtype ~= "source" and neigh_def.liquidtype ~= "flowing" then return end -- Non-liquids can't flow at all.
local neigh_flowing = neigh_def.liquid_alternative_flowing
if not neigh_flowing then return end -- Improperly configured liquids can't flow.
-- Check the opposing neighbor.
local opposite = vector.subtract(pos, offset)
local flowto_opposite = true
local opposite_level = calculate_level(opposite)
if opposite_level > level - 2 then flowto_opposite = false end
local flow_to = opposite
local gravity_affected = false
if vector.equals(offset, {x=0, y=-1, z=0}) then
-- Silly code, water can't flow UP!
return
elseif vector.equals(offset, {x=0, y=1, z=0}) then
-- Water is very good at flowing down. Set to a high value.
minetest.set_node(flow_to, {
name = neigh_flowing,
param1 = neigh_node.param1,
param2 = 6
})
return
else
-- Great, water is flowing from the side, but what if the grate is above air?
-- We should check if the water can flow down, first.
local grav = vector.subtract(pos, {x=0, y=1, z=0})
-- Meet the grav_node - the node that's below the grate.
-- If liquids can flow into this node, we can forget about the opposite_node.
local grav_level = calculate_level(grav)
if grav_level < level - 2 then
-- OOP! Sudden course change!
flow_to = grav
gravity_affected = true
end
end
local new_param2 = neigh_def.liquidtype == "source" and 6 or neigh_node.param2 - 2
if new_param2 < 0 then return end
if flowto_opposite then
minetest.set_node(flow_to, {
name = neigh_flowing,
param1 = neigh_node.param1,
param2 = new_param2
})
end
-- And we're done.
-- WAIT! We're not done.
if offset.y == 0 and not gravity_affected then
local left_flow = {x = offset.z, y = 0, z = -offset.x}
local left_pos = vector.add(pos, left_flow)
local right_flow = {x = -offset.z, y = 0, z = offset.x}
local right_pos = vector.add(pos, right_flow)
local left_level = calculate_level(left_pos)
local right_level = calculate_level(right_pos)
if left_level < level - 2 then
-- May as well spread here, too.
minetest.set_node(left_pos, {
name = neigh_flowing,
param1 = neigh_node.param1,
param2 = new_param2
})
end
if right_level < level - 2 then
-- May as well spread here, too.
minetest.set_node(right_pos, {
name = neigh_flowing,
param1 = neigh_node.param1,
param2 = new_param2
})
end
end]]
end
minetest.register_abm({
label = "Grate Step",
nodenames = {"rmod:grate"},
neighbors = {},
interval = 1,
chance = 1,
action = function (pos, node)
for i=1,5 do -- For each of our 5 neighbors, (excluding the node from below, of course)
-- Calculate where our neighbor is
local offset = {x=0,y=0,z=0}
if i == 1 then offset.y = 1 end
--if i == 2 then offset.y = -1 end
if i == 2 then offset.x = 1 end
if i == 3 then offset.x = -1 end
if i == 4 then offset.z = 1 end
if i == 5 then offset.z = -1 end
-- Then run the checking code
grate_step(pos, offset)
end
end,
})