mirror of
https://git.minetest.land/VoxeLibre/VoxeLibre.git
synced 2024-11-30 22:41:20 +01:00
make mcl_util.call_safe and use it to make sure that mesecon devices are isolated from each other and can't crash the server, handle powered solid blocks, increase powered on to 16
This commit is contained in:
parent
6107bba52f
commit
e970a5f414
4 changed files with 61 additions and 25 deletions
|
@ -1225,3 +1225,16 @@ function mcl_util.metadata_last_act(meta, name, delay)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Call a function safely and provide a backtrace on error
|
||||||
|
function mcl_util.call_safe(label, func, args)
|
||||||
|
local function caller()
|
||||||
|
return func(unpack(args))
|
||||||
|
end
|
||||||
|
|
||||||
|
local ok,ret = xpcall(caller, debug.traceback)
|
||||||
|
if not ok then
|
||||||
|
minetest.log("error",(label or "")..ret)
|
||||||
|
end
|
||||||
|
|
||||||
|
return ok,ret
|
||||||
|
end
|
||||||
|
|
|
@ -4,6 +4,9 @@ local modpath = minetest.get_modpath(modname)
|
||||||
vl_scheduler = {}
|
vl_scheduler = {}
|
||||||
local mod = vl_scheduler
|
local mod = vl_scheduler
|
||||||
|
|
||||||
|
-- Imports
|
||||||
|
local call_safe = mcl_util.call_safe
|
||||||
|
|
||||||
dofile(modpath.."/queue.lua")
|
dofile(modpath.."/queue.lua")
|
||||||
dofile(modpath.."/fifo.lua")
|
dofile(modpath.."/fifo.lua")
|
||||||
dofile(modpath.."/test.lua")
|
dofile(modpath.."/test.lua")
|
||||||
|
@ -129,13 +132,10 @@ local function run_scheduler(dtime)
|
||||||
local func = functions[task.fid]
|
local func = functions[task.fid]
|
||||||
if func then
|
if func then
|
||||||
--print("Running task "..dump(task)..",func="..dump(func))
|
--print("Running task "..dump(task)..",func="..dump(func))
|
||||||
local function caller()
|
local ok,ret = call_safe(
|
||||||
return func.func(task, unpack(task.args or {}))
|
"Error while running task "..func.name..": ",
|
||||||
end
|
func.func, {task, unpack(task.args or {})}
|
||||||
local ok,ret = xpcall(caller, debug.traceback)
|
)
|
||||||
if not ok then
|
|
||||||
minetest.log("error","Error while running task "..func.name..": "..tostring(ret))
|
|
||||||
end
|
|
||||||
|
|
||||||
-- If the task was returned, reschedule it
|
-- If the task was returned, reschedule it
|
||||||
if ret == task then
|
if ret == task then
|
||||||
|
|
|
@ -52,7 +52,7 @@ minetest.register_node("mesecons_walllever:wall_lever_off", {
|
||||||
_doc_items_usagehelp = S("Use the lever to flip it on or off."),
|
_doc_items_usagehelp = S("Use the lever to flip it on or off."),
|
||||||
on_rightclick = function(pos, node)
|
on_rightclick = function(pos, node)
|
||||||
minetest.swap_node(pos, {name="mesecons_walllever:wall_lever_on", param2=node.param2})
|
minetest.swap_node(pos, {name="mesecons_walllever:wall_lever_on", param2=node.param2})
|
||||||
vl_redstone.set_power(pos, 15)
|
vl_redstone.set_power(pos, 16)
|
||||||
minetest.sound_play("mesecons_button_push", {pos=pos, max_hear_distance=16}, true)
|
minetest.sound_play("mesecons_button_push", {pos=pos, max_hear_distance=16}, true)
|
||||||
end,
|
end,
|
||||||
node_placement_prediction = "",
|
node_placement_prediction = "",
|
||||||
|
|
|
@ -36,17 +36,18 @@ local function update_sink(pos)
|
||||||
local last_strength = meta:get_int(REDSTONE_POWER_META_LAST_STATE)
|
local last_strength = meta:get_int(REDSTONE_POWER_META_LAST_STATE)
|
||||||
|
|
||||||
if last_strength ~= strength then
|
if last_strength ~= strength then
|
||||||
|
print("Updating "..node.name.." at "..vector.to_string(pos).."("..tostring(last_strength).."->"..tostring(strength)..")")
|
||||||
-- Inform the node of changes
|
-- Inform the node of changes
|
||||||
if strength > 0 then
|
if strength > 0 then
|
||||||
-- Handle activation
|
-- Handle activation
|
||||||
if sink.action_on then
|
if sink.action_on then
|
||||||
sink.action_on(pos, node)
|
mcl_util.call_safe(nil, sink.action_on, {pos, node})
|
||||||
end
|
end
|
||||||
|
|
||||||
else
|
else
|
||||||
-- Handle deactivation
|
-- Handle deactivation
|
||||||
if sink.action_off then
|
if sink.action_off then
|
||||||
sink.action_off(pos, node)
|
mcl_util.call_safe(nil, sink.action_off, {pos, node})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -57,28 +58,52 @@ local function update_sink(pos)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function get_positions_from_node_rules(pos, rules_type, list)
|
local POWERED_BLOCK_RULES = {
|
||||||
|
vector.new( 1, 0, 0),
|
||||||
|
vector.new(-1, 0, 0),
|
||||||
|
vector.new( 0, 1, 0),
|
||||||
|
vector.new( 0,-1, 0),
|
||||||
|
vector.new( 0, 0, 1),
|
||||||
|
vector.new( 0, 0,-1),
|
||||||
|
}
|
||||||
|
|
||||||
|
local function get_positions_from_node_rules(pos, rules_type, list, powered)
|
||||||
list = list or {}
|
list = list or {}
|
||||||
|
|
||||||
local node = minetest.get_node(pos)
|
local node = minetest.get_node(pos)
|
||||||
local nodedef = minetest.registered_nodes[node.name]
|
local nodedef = minetest.registered_nodes[node.name]
|
||||||
if not nodedef.mesecons then return list end
|
local rules
|
||||||
|
if nodedef.mesecons then
|
||||||
-- Get mesecons rules
|
-- Get mesecons rules
|
||||||
if not nodedef.mesecons[rules_type] then
|
if not nodedef.mesecons[rules_type] then
|
||||||
minetest.log("info","Node "..node.name.." has no mesecons."..rules_type.." rules")
|
minetest.log("info","Node "..node.name.." has no mesecons."..rules_type.." rules")
|
||||||
return list
|
return list
|
||||||
end
|
end
|
||||||
local rules = nodedef.mesecons[rules_type].rules
|
rules = nodedef.mesecons[rules_type].rules
|
||||||
if type(rules) == "function" then rules = rules(node) end
|
if type(rules) == "function" then rules = rules(node) end
|
||||||
|
else
|
||||||
|
-- The only blocks that don't support mesecon that propagate power are solid blocks that
|
||||||
|
-- are powered by another device. Mesecons calls this 'spread'
|
||||||
|
if not powered[vector.to_string(pos)] then return list end
|
||||||
|
if minetest.get_item_group(node.name,"solid") == 0 then return list end
|
||||||
|
|
||||||
--print("rules="..dump(rules))
|
rules = POWERED_BLOCK_RULES
|
||||||
|
end
|
||||||
|
|
||||||
|
print("rules="..dump(rules))
|
||||||
|
|
||||||
-- Convert to absolute positions
|
-- Convert to absolute positions
|
||||||
for i=1,#rules do
|
for i=1,#rules do
|
||||||
local next_pos = vector.add(pos, rules[i])
|
local next_pos = vector.add(pos, rules[i])
|
||||||
local next_pos_str = vector.to_string(next_pos)
|
local next_pos_str = vector.to_string(next_pos)
|
||||||
|
print("\tnext: "..next_pos_str..", prev="..tostring(list[next_pos_str]))
|
||||||
list[next_pos_str] = true
|
list[next_pos_str] = true
|
||||||
|
|
||||||
|
-- Power solid blocks
|
||||||
|
if rules[i].spread then
|
||||||
|
powered[next_pos_str] = true
|
||||||
|
print("powering "..next_pos_str)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return list
|
return list
|
||||||
|
@ -87,6 +112,7 @@ end
|
||||||
vl_scheduler.register_function("vl_redstone:flow_power",function(task, source_pos, strength, distance)
|
vl_scheduler.register_function("vl_redstone:flow_power",function(task, source_pos, strength, distance)
|
||||||
print("Flowing lv"..tostring(strength).." power from "..vector.to_string(source_pos).." for "..tostring(distance).." blocks")
|
print("Flowing lv"..tostring(strength).." power from "..vector.to_string(source_pos).." for "..tostring(distance).." blocks")
|
||||||
local processed = {}
|
local processed = {}
|
||||||
|
local powered = {}
|
||||||
local source_pos_str = vector.to_string(source_pos)
|
local source_pos_str = vector.to_string(source_pos)
|
||||||
|
|
||||||
-- Update the source node's redstone power
|
-- Update the source node's redstone power
|
||||||
|
@ -95,8 +121,8 @@ vl_scheduler.register_function("vl_redstone:flow_power",function(task, source_po
|
||||||
|
|
||||||
-- Get rules
|
-- Get rules
|
||||||
local list = {}
|
local list = {}
|
||||||
get_positions_from_node_rules(source_pos, "receptor", list)
|
get_positions_from_node_rules(source_pos, "receptor", list, powered)
|
||||||
print("initial list="..dump(list))
|
--print("initial list="..dump(list))
|
||||||
|
|
||||||
for i=1,distance do
|
for i=1,distance do
|
||||||
local next_list = {}
|
local next_list = {}
|
||||||
|
@ -117,10 +143,7 @@ vl_scheduler.register_function("vl_redstone:flow_power",function(task, source_po
|
||||||
print("pos="..vector.to_string(pos)..", strength="..tostring(strength))
|
print("pos="..vector.to_string(pos)..", strength="..tostring(strength))
|
||||||
|
|
||||||
-- handle spread
|
-- handle spread
|
||||||
local spread_to = get_positions_from_node_rules(pos, "conductor")
|
get_positions_from_node_rules(pos, "conductor", next_list, powered)
|
||||||
for j=1,#spread_to do
|
|
||||||
next_list[vector.to_string(spread_to[j])] = true
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Update the position
|
-- Update the position
|
||||||
update_sink(pos)
|
update_sink(pos)
|
||||||
|
|
Loading…
Reference in a new issue