diff --git a/mods/CORE/mcl_util/init.lua b/mods/CORE/mcl_util/init.lua index d537749ef..4ae0f7dc5 100644 --- a/mods/CORE/mcl_util/init.lua +++ b/mods/CORE/mcl_util/init.lua @@ -1238,3 +1238,25 @@ function mcl_util.call_safe(label, func, args) return ok,ret end + +function mcl_util.force_get_node(pos) + local node = minetest.get_node(pos) + if node.name ~= "ignore" then return node end + + local vm = minetest.get_voxel_manip() + local emin, emax = vm:read_from_map(pos, pos) + local area = VoxelArea:new{ + MinEdge = emin, + MaxEdge = emax, + } + local data = vm:get_data() + local param_data = vm:get_light_data() + local param2_data = vm:get_param2_data() + + local vi = area:indexp(pos) + return { + name = minetest.get_name_from_content_id(data[vi]), + param = param_data[vi], + param2 = param2_data[vi] + } +end diff --git a/mods/ENTITIES/mcl_minecarts/functions.lua b/mods/ENTITIES/mcl_minecarts/functions.lua index d476d606b..68cc16c94 100644 --- a/mods/ENTITIES/mcl_minecarts/functions.lua +++ b/mods/ENTITIES/mcl_minecarts/functions.lua @@ -7,27 +7,7 @@ function get_path(base, first, ...) if not base then return end return get_path(base[first], ...) end -local function force_get_node(pos) - local node = minetest.get_node(pos) - if node.name ~= "ignore" then return node end - - local vm = minetest.get_voxel_manip() - local emin, emax = vm:read_from_map(pos, pos) - local area = VoxelArea:new{ - MinEdge = emin, - MaxEdge = emax, - } - local data = vm:get_data() - local param_data = vm:get_light_data() - local param2_data = vm:get_param2_data() - - local vi = area:indexp(pos) - return { - name = minetest.get_name_from_content_id(data[vi]), - param = param_data[vi], - param2 = param2_data[vi] - } -end +local force_get_node = mcl_util.force_get_node function mcl_minecarts:get_sign(z) if z == 0 then diff --git a/mods/ITEMS/REDSTONE/mcl_comparators/init.lua b/mods/ITEMS/REDSTONE/mcl_comparators/init.lua index 2ad8257b9..a8efd4246 100644 --- a/mods/ITEMS/REDSTONE/mcl_comparators/init.lua +++ b/mods/ITEMS/REDSTONE/mcl_comparators/init.lua @@ -34,6 +34,7 @@ local POSSIBLE_COMPARATOR_POSITIONS = { -- update comparator state, if needed local function update_self(pos, node) node = node or minetest.get_node(pos) + local nodedef = minetest.registered_nodes[node.name] -- Find the node we are pointing at local input_rules = comparator_get_input_rules(node); @@ -43,7 +44,7 @@ local function update_self(pos, node) local back_nodedef = minetest.registered_nodes[back_node.name] -- Get the comparator mode - local mode = minetest.registered_nodes[node.name].comparator_mode + local mode = nodedef.comparator_mode -- Get a comparator reading from the block at the back of the comparator local power_level = 0 @@ -70,7 +71,17 @@ local function update_self(pos, node) end end + -- Update output power level vl_redstone.set_power(pos, power_level) + + -- Update node + if power_level ~= 0 then + node.name = nodedef.comparator_onstate + minetest.swap_node(pos, node) + else + node.name = nodedef.comparator_offstate + minetest.swap_node(pos, node) + end end function mod.trigger_update(pos) diff --git a/mods/ITEMS/REDSTONE/vl_redstone/init.lua b/mods/ITEMS/REDSTONE/vl_redstone/init.lua index f6fd00d62..4d6d0518c 100644 --- a/mods/ITEMS/REDSTONE/vl_redstone/init.lua +++ b/mods/ITEMS/REDSTONE/vl_redstone/init.lua @@ -3,57 +3,117 @@ local modpath = minetest.get_modpath(modname) vl_redstone = {} local mod = vl_redstone +-- Imports +local force_get_node = mcl_util.force_get_node +local call_safe = mcl_util.call_safe +local get_item_group = minetest.get_item_group +local get_meta = minetest.get_meta +local vector_add = vector.add +local vector_to_string = vector.to_string +local vector_from_string = vector.from_string + +-- Constants local REDSTONE_POWER_META = modname .. ".power" local REDSTONE_POWER_META_SOURCE = REDSTONE_POWER_META.."." -local function update_sink(pos) - local node = minetest.get_node(pos) +local function update_node(pos) + local node = force_get_node(pos) local nodedef = minetest.registered_nodes[node.name] -- Only do this processing of signal sinks if not nodedef.mesecons then return end - local sink = nodedef.mesecons.effector - if not sink then return end - - local meta = minetest.get_meta(pos) -- Calculate the maximum power feeding into this node + -- TODO: check how much time this is taking + local meta = minetest.get_meta(pos) local strength = 0 local meta_tbl = meta:to_table() for k,v in pairs(meta_tbl.fields) do if string.sub(k,1,#REDSTONE_POWER_META_SOURCE) == REDSTONE_POWER_META_SOURCE then - --local source_pos_str = string.sub(k,#REDSTONE_POWER_META_SOURCE+1) - --print("\tsource_pos_str="..source_pos_str) local source_strength = tonumber(v) - --print("\tstrength="..source_strength) if source_strength > strength then strength = source_strength end end end + -- Don't do any processing inf the actual strength at this node has changed local last_strength = meta:get_int(REDSTONE_POWER_META) + if last_strength == strength then return end - if last_strength ~= strength then - --print("Updating "..node.name.." at "..vector.to_string(pos).."("..tostring(last_strength).."->"..tostring(strength)..")") + -- Update the state + meta:set_int(REDSTONE_POWER_META, strength) + + -- TODO: determine the input rule that the strength is coming from + local rule = nil + + local sink = nodedef.mesecons.effector + if sink then + local new_node_name = nil + --print("Updating "..node.name.." at "..vector_to_string(pos).."("..tostring(last_strength).."->"..tostring(strength)..")") -- Inform the node of changes - if strength > 0 then + if strength ~= 0 and last_strength == 0 then -- Handle activation - if sink.action_on then - mcl_util.call_safe(nil, sink.action_on, {pos, node}) + local hook = sink.action_on + if hook then + call_safe(nil, hook, {pos, node, rule, strength}) end - - else + if sink.onstate then + new_node_name = sink.onstate + end + elseif strength == 0 and last_strength ~= 0 then -- Handle deactivation - if sink.action_off then - mcl_util.call_safe(nil, sink.action_off, {pos, node}) + local hook = sink.action_off + if hook then + call_safe(nil, hook, {pos, node, rule, strength}) + end + if sink.offstate then + new_node_name = sink.offstate end end -- TODO: handle signal level change notification + local hook = sink.action_change + if hook then + call_safe(nil, hook, {pos, node, rule, strength}) + end + if sink.strength_state then + new_node_name = sink.strength_state[strength] + end - -- Update the state as the last thing in case there is a crash in the above code - meta:set_int(REDSTONE_POWER_META, strength) + -- Update the node + if new_node_name and new_node_name ~= node.name then + node.name = new_node_name + minetest.swap_node(pos, node) + end + return + end + + local conductor = nodedef.mesecons.conductor + if conductor then + -- Figure out if the node name changes based on the new state + local new_node_name = nil + if conductor.strength_state then + new_node_name = conductor.strength_state[strength] + elseif strength > 0 and conductor.onstate then + new_node_name = conductor.onstate + elseif strength == 0 and conductor.offstate then + new_node_name = conductor.offstate + end + + -- Update the node + if new_node_name and new_node_name ~= node.name then + --[[ + print("Changing "..vector_to_string(pos).." from "..node.name.." to "..new_node_name.. + ", strength="..tostring(strength)..",last_strength="..tostring(last_strength)) + print("node.name="..node.name.. + ",conductor.onstate="..tostring(conductor.onstate).. + ",conductor.offstate="..tostring(conductor.offstate) + ) + ]] + node.name = new_node_name + minetest.swap_node(pos, node) + end end end @@ -69,7 +129,7 @@ local POWERED_BLOCK_RULES = { local function get_positions_from_node_rules(pos, rules_type, list, powered) list = list or {} - local node = minetest.get_node(pos) + local node = force_get_node(pos) local nodedef = minetest.registered_nodes[node.name] local rules if nodedef.mesecons then @@ -83,8 +143,8 @@ local function get_positions_from_node_rules(pos, rules_type, list, powered) 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 + if not powered[vector_to_string(pos)] then return list end + if get_item_group(node.name,"solid") == 0 then return list end rules = POWERED_BLOCK_RULES end @@ -93,8 +153,8 @@ local function get_positions_from_node_rules(pos, rules_type, list, powered) -- Convert to absolute positions for i=1,#rules do - local next_pos = vector.add(pos, rules[i]) - local next_pos_str = vector.to_string(next_pos) + local next_pos = vector_add(pos, rules[i]) + 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 @@ -109,14 +169,14 @@ local function get_positions_from_node_rules(pos, rules_type, list, powered) end vl_scheduler.register_function("vl_redstone:flow_power",function(task, source_pos, source_strength, distance) - print("Flowing lv"..tostring(source_strength).." power from "..vector.to_string(source_pos).." for "..tostring(distance).." blocks") + print("Flowing lv"..tostring(source_strength).." power from "..vector_to_string(source_pos).." for "..tostring(distance).." blocks") local processed = {} local powered = {} - local source_pos_str = vector.to_string(source_pos) + local source_pos_str = vector_to_string(source_pos) processed[source_pos_str] = true -- Update the source node's redstone power - local meta = minetest.get_meta(source_pos) + local meta = get_meta(source_pos) meta:set_int(REDSTONE_POWER_META, source_strength) -- Get rules @@ -135,8 +195,8 @@ vl_scheduler.register_function("vl_redstone:flow_power",function(task, source_po if not processed[pos_str] then processed[pos_str] = true - local pos = vector.from_string(pos_str) - local meta = minetest.get_meta(pos) + local pos = vector_from_string(pos_str) + local meta = get_meta(pos) -- Update node power directly meta:set_int(REDSTONE_POWER_META.."."..source_pos_str, strength) @@ -146,7 +206,7 @@ vl_scheduler.register_function("vl_redstone:flow_power",function(task, source_po get_positions_from_node_rules(pos, "conductor", next_list, powered) -- Update the position - update_sink(pos) + update_node(pos) end end @@ -156,7 +216,7 @@ vl_scheduler.register_function("vl_redstone:flow_power",function(task, source_po end) function vl_redstone.set_power(pos, strength) - local meta = minetest.get_meta(pos) + local meta = get_meta(pos) local distance = meta:get_int(REDSTONE_POWER_META) -- Don't perform an update if the power level is the same as before @@ -174,7 +234,7 @@ function vl_redstone.set_power(pos, strength) end function vl_redstone.get_power_level(pos) - local meta = minetest.get_meta(pos) + local meta = get_meta(pos) return meta:get_int(REDSTONE_POWER_META) end