Completely rewritten the grate's flowing mechanics to use more modular subroutines and functions.
This commit is contained in:
parent
06a195e08f
commit
c2c48ebebe
149
grate.lua
149
grate.lua
|
@ -3,48 +3,103 @@ minetest.register_node("rmod:grate", {
|
||||||
tiles = {"rmod_grate.png"},
|
tiles = {"rmod_grate.png"},
|
||||||
groups = {oddly_breakable_by_hand = 1},
|
groups = {oddly_breakable_by_hand = 1},
|
||||||
use_texture_alpha = true,
|
use_texture_alpha = true,
|
||||||
drawtype = "glasslike",
|
drawtype = "allfaces", --"glasslike",
|
||||||
paramtype = "light",
|
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 function grate_step(pos, offset)
|
||||||
local neigh = vector.add(pos, offset)
|
local pos1 = vector.add(pos, offset)
|
||||||
local neigh_node = minetest.get_node(neigh)
|
|
||||||
local neigh_name
|
if not attempt_flow_to(pos1, vector.subtract(pos, {x=0,y=1,z=0}), 2) then -- If we can't flow below...
|
||||||
if neigh_node then neigh_name = neigh_node.name else return end
|
local left_offset = {x = offset.z, y = 0, z = -offset.x}
|
||||||
local neigh_def = minetest.registered_nodes[neigh_name]
|
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 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.
|
if neigh_def.liquidtype ~= "source" and neigh_def.liquidtype ~= "flowing" then return end -- Non-liquids can't flow at all.
|
||||||
|
|
||||||
-- Check its level.
|
|
||||||
local level = neigh_node.param2 % 16
|
|
||||||
if level > 8 then level = level - 8 end
|
|
||||||
if neigh_def.liquidtype == "source" then level = 8 end
|
|
||||||
|
|
||||||
-- Check the opposing neighbor.
|
|
||||||
local opposite = vector.subtract(pos, offset)
|
|
||||||
local opposite_node = minetest.get_node(opposite)
|
|
||||||
local opposite_name
|
|
||||||
if opposite_node then opposite_name = opposite_node.name else return end
|
|
||||||
local opposite_def = minetest.registered_nodes[opposite_name]
|
|
||||||
if not opposite_def then return end
|
|
||||||
|
|
||||||
local flowto_opposite = true
|
|
||||||
|
|
||||||
if not opposite_def.floodable then
|
|
||||||
if not opposite_def.liquidtype then flowto_opposite = false end
|
|
||||||
if opposite_def.walkable then flowto_opposite = false end
|
|
||||||
|
|
||||||
local opposite_level = opposite_node.param2 % 16
|
|
||||||
if opposite_level > 8 then opposite_level = opposite_level - 8 end
|
|
||||||
if opposite_def.liquidtype == "source" then opposite_level = 8 end
|
|
||||||
|
|
||||||
if opposite_level > level - 2 or opposite_def.liquidtype == "source" then flowto_opposite = false end
|
|
||||||
end -- Liquids can't flow into higher level liquids.
|
|
||||||
local neigh_flowing = neigh_def.liquid_alternative_flowing
|
local neigh_flowing = neigh_def.liquid_alternative_flowing
|
||||||
if not neigh_flowing then return end -- Improperly configured liquids can't flow.
|
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 flow_to = opposite
|
||||||
|
local gravity_affected = false
|
||||||
|
|
||||||
if vector.equals(offset, {x=0, y=-1, z=0}) then
|
if vector.equals(offset, {x=0, y=-1, z=0}) then
|
||||||
-- Silly code, water can't flow UP!
|
-- Silly code, water can't flow UP!
|
||||||
|
@ -61,16 +116,16 @@ local function grate_step(pos, offset)
|
||||||
-- Great, water is flowing from the side, but what if the grate is above air?
|
-- 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.
|
-- We should check if the water can flow down, first.
|
||||||
local grav = vector.subtract(pos, {x=0, y=1, z=0})
|
local grav = vector.subtract(pos, {x=0, y=1, z=0})
|
||||||
local grav_node = minetest.get_node(grav)
|
|
||||||
local grav_name
|
|
||||||
if grav_node then grav_name = grav_node.name end
|
|
||||||
|
|
||||||
-- Meet the grav_node - the node that's below the grate.
|
-- 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.
|
-- If liquids can flow into this node, we can forget about the opposite_node.
|
||||||
|
|
||||||
if grav_node and grav_name == "air" then
|
local grav_level = calculate_level(grav)
|
||||||
|
|
||||||
|
if grav_level < level - 2 then
|
||||||
-- OOP! Sudden course change!
|
-- OOP! Sudden course change!
|
||||||
flow_to = grav
|
flow_to = grav
|
||||||
|
gravity_affected = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -88,29 +143,17 @@ local function grate_step(pos, offset)
|
||||||
|
|
||||||
|
|
||||||
-- WAIT! We're not done.
|
-- WAIT! We're not done.
|
||||||
if offset.y == 0 then
|
if offset.y == 0 and not gravity_affected then
|
||||||
local left_flow = {x = offset.z, y = 0, z = -offset.x}
|
local left_flow = {x = offset.z, y = 0, z = -offset.x}
|
||||||
local left_pos = vector.add(pos, left_flow)
|
local left_pos = vector.add(pos, left_flow)
|
||||||
local left_node = minetest.get_node(left_pos)
|
|
||||||
local left_name
|
|
||||||
if left_node then left_name = left_node.name end
|
|
||||||
local left_def = left_name and minetest.registered_nodes[left_name]
|
|
||||||
local right_flow = {x = -offset.z, y = 0, z = offset.x}
|
local right_flow = {x = -offset.z, y = 0, z = offset.x}
|
||||||
local right_pos = vector.add(pos, right_flow)
|
local right_pos = vector.add(pos, right_flow)
|
||||||
local right_node = minetest.get_node(right_pos)
|
|
||||||
local right_name
|
|
||||||
if right_node then right_name = right_node.name end
|
|
||||||
local right_def = right_name and minetest.registered_nodes[right_name]
|
|
||||||
|
|
||||||
local left_level = left_node.param2 % 16
|
local left_level = calculate_level(left_pos)
|
||||||
if left_level > 8 then left_level = left_level - 8 end
|
|
||||||
if left_def.liquidtype == "source" then left_level = 8 end
|
|
||||||
|
|
||||||
local right_level = right_node.param2 % 16
|
local right_level = calculate_level(right_pos)
|
||||||
if right_level > 8 then right_level = right_level - 8 end
|
|
||||||
if right_def.liquidtype == "source" then right_level = 8 end
|
|
||||||
|
|
||||||
if left_node and (left_name == "air" or (left_def.liquidtype == "flowing" and left_level < level - 2)) then
|
if left_level < level - 2 then
|
||||||
-- May as well spread here, too.
|
-- May as well spread here, too.
|
||||||
minetest.set_node(left_pos, {
|
minetest.set_node(left_pos, {
|
||||||
name = neigh_flowing,
|
name = neigh_flowing,
|
||||||
|
@ -118,7 +161,7 @@ local function grate_step(pos, offset)
|
||||||
param2 = new_param2
|
param2 = new_param2
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
if right_node and (right_name == "air" or (right_def.liquidtype == "flowing" and right_level < level - 2)) then
|
if right_level < level - 2 then
|
||||||
-- May as well spread here, too.
|
-- May as well spread here, too.
|
||||||
minetest.set_node(right_pos, {
|
minetest.set_node(right_pos, {
|
||||||
name = neigh_flowing,
|
name = neigh_flowing,
|
||||||
|
@ -126,7 +169,7 @@ local function grate_step(pos, offset)
|
||||||
param2 = new_param2
|
param2 = new_param2
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
end
|
end]]
|
||||||
end
|
end
|
||||||
|
|
||||||
minetest.register_abm({
|
minetest.register_abm({
|
||||||
|
|
Reference in New Issue