mirror of
https://git.minetest.land/VoxeLibre/VoxeLibre.git
synced 2025-01-07 15:49:32 +01:00
Move force_get_node to mcl_util and swap all minetest.get_node to force_get_node in the new redstone code, implement conductors
This commit is contained in:
parent
13888236d6
commit
6396b6f56c
4 changed files with 128 additions and 55 deletions
|
@ -1238,3 +1238,25 @@ function mcl_util.call_safe(label, func, args)
|
||||||
|
|
||||||
return ok,ret
|
return ok,ret
|
||||||
end
|
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
|
||||||
|
|
|
@ -7,27 +7,7 @@ function get_path(base, first, ...)
|
||||||
if not base then return end
|
if not base then return end
|
||||||
return get_path(base[first], ...)
|
return get_path(base[first], ...)
|
||||||
end
|
end
|
||||||
local function force_get_node(pos)
|
local force_get_node = mcl_util.force_get_node
|
||||||
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
|
|
||||||
|
|
||||||
function mcl_minecarts:get_sign(z)
|
function mcl_minecarts:get_sign(z)
|
||||||
if z == 0 then
|
if z == 0 then
|
||||||
|
|
|
@ -34,6 +34,7 @@ local POSSIBLE_COMPARATOR_POSITIONS = {
|
||||||
-- update comparator state, if needed
|
-- update comparator state, if needed
|
||||||
local function update_self(pos, node)
|
local function update_self(pos, node)
|
||||||
node = node or minetest.get_node(pos)
|
node = node or minetest.get_node(pos)
|
||||||
|
local nodedef = minetest.registered_nodes[node.name]
|
||||||
|
|
||||||
-- Find the node we are pointing at
|
-- Find the node we are pointing at
|
||||||
local input_rules = comparator_get_input_rules(node);
|
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]
|
local back_nodedef = minetest.registered_nodes[back_node.name]
|
||||||
|
|
||||||
-- Get the comparator mode
|
-- 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
|
-- Get a comparator reading from the block at the back of the comparator
|
||||||
local power_level = 0
|
local power_level = 0
|
||||||
|
@ -70,7 +71,17 @@ local function update_self(pos, node)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Update output power level
|
||||||
vl_redstone.set_power(pos, 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
|
end
|
||||||
|
|
||||||
function mod.trigger_update(pos)
|
function mod.trigger_update(pos)
|
||||||
|
|
|
@ -3,57 +3,117 @@ local modpath = minetest.get_modpath(modname)
|
||||||
vl_redstone = {}
|
vl_redstone = {}
|
||||||
local mod = 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 = modname .. ".power"
|
||||||
local REDSTONE_POWER_META_SOURCE = REDSTONE_POWER_META.."."
|
local REDSTONE_POWER_META_SOURCE = REDSTONE_POWER_META.."."
|
||||||
|
|
||||||
local function update_sink(pos)
|
local function update_node(pos)
|
||||||
local node = minetest.get_node(pos)
|
local node = force_get_node(pos)
|
||||||
local nodedef = minetest.registered_nodes[node.name]
|
local nodedef = minetest.registered_nodes[node.name]
|
||||||
|
|
||||||
-- Only do this processing of signal sinks
|
-- Only do this processing of signal sinks
|
||||||
if not nodedef.mesecons then return end
|
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
|
-- 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 strength = 0
|
||||||
local meta_tbl = meta:to_table()
|
local meta_tbl = meta:to_table()
|
||||||
for k,v in pairs(meta_tbl.fields) do
|
for k,v in pairs(meta_tbl.fields) do
|
||||||
if string.sub(k,1,#REDSTONE_POWER_META_SOURCE) == REDSTONE_POWER_META_SOURCE then
|
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)
|
local source_strength = tonumber(v)
|
||||||
--print("\tstrength="..source_strength)
|
|
||||||
if source_strength > strength then
|
if source_strength > strength then
|
||||||
strength = source_strength
|
strength = source_strength
|
||||||
end
|
end
|
||||||
end
|
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)
|
local last_strength = meta:get_int(REDSTONE_POWER_META)
|
||||||
|
if last_strength == strength then return end
|
||||||
|
|
||||||
if last_strength ~= strength then
|
-- Update the state
|
||||||
--print("Updating "..node.name.." at "..vector.to_string(pos).."("..tostring(last_strength).."->"..tostring(strength)..")")
|
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
|
-- Inform the node of changes
|
||||||
if strength > 0 then
|
if strength ~= 0 and last_strength == 0 then
|
||||||
-- Handle activation
|
-- Handle activation
|
||||||
if sink.action_on then
|
local hook = sink.action_on
|
||||||
mcl_util.call_safe(nil, sink.action_on, {pos, node})
|
if hook then
|
||||||
|
call_safe(nil, hook, {pos, node, rule, strength})
|
||||||
end
|
end
|
||||||
|
if sink.onstate then
|
||||||
else
|
new_node_name = sink.onstate
|
||||||
|
end
|
||||||
|
elseif strength == 0 and last_strength ~= 0 then
|
||||||
-- Handle deactivation
|
-- Handle deactivation
|
||||||
if sink.action_off then
|
local hook = sink.action_off
|
||||||
mcl_util.call_safe(nil, sink.action_off, {pos, node})
|
if hook then
|
||||||
|
call_safe(nil, hook, {pos, node, rule, strength})
|
||||||
|
end
|
||||||
|
if sink.offstate then
|
||||||
|
new_node_name = sink.offstate
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- TODO: handle signal level change notification
|
-- 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
|
-- Update the node
|
||||||
meta:set_int(REDSTONE_POWER_META, strength)
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -69,7 +129,7 @@ local POWERED_BLOCK_RULES = {
|
||||||
local function get_positions_from_node_rules(pos, rules_type, list, powered)
|
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 = force_get_node(pos)
|
||||||
local nodedef = minetest.registered_nodes[node.name]
|
local nodedef = minetest.registered_nodes[node.name]
|
||||||
local rules
|
local rules
|
||||||
if nodedef.mesecons then
|
if nodedef.mesecons then
|
||||||
|
@ -83,8 +143,8 @@ local function get_positions_from_node_rules(pos, rules_type, list, powered)
|
||||||
else
|
else
|
||||||
-- The only blocks that don't support mesecon that propagate power are solid blocks that
|
-- The only blocks that don't support mesecon that propagate power are solid blocks that
|
||||||
-- are powered by another device. Mesecons calls this 'spread'
|
-- are powered by another device. Mesecons calls this 'spread'
|
||||||
if not powered[vector.to_string(pos)] then return list end
|
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 get_item_group(node.name,"solid") == 0 then return list end
|
||||||
|
|
||||||
rules = POWERED_BLOCK_RULES
|
rules = POWERED_BLOCK_RULES
|
||||||
end
|
end
|
||||||
|
@ -93,8 +153,8 @@ local function get_positions_from_node_rules(pos, rules_type, list, powered)
|
||||||
|
|
||||||
-- 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]))
|
--print("\tnext: "..next_pos_str..", prev="..tostring(list[next_pos_str]))
|
||||||
list[next_pos_str] = true
|
list[next_pos_str] = true
|
||||||
|
|
||||||
|
@ -109,14 +169,14 @@ local function get_positions_from_node_rules(pos, rules_type, list, powered)
|
||||||
end
|
end
|
||||||
|
|
||||||
vl_scheduler.register_function("vl_redstone:flow_power",function(task, source_pos, source_strength, distance)
|
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 processed = {}
|
||||||
local powered = {}
|
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
|
processed[source_pos_str] = true
|
||||||
|
|
||||||
-- Update the source node's redstone power
|
-- 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)
|
meta:set_int(REDSTONE_POWER_META, source_strength)
|
||||||
|
|
||||||
-- Get rules
|
-- Get rules
|
||||||
|
@ -135,8 +195,8 @@ vl_scheduler.register_function("vl_redstone:flow_power",function(task, source_po
|
||||||
if not processed[pos_str] then
|
if not processed[pos_str] then
|
||||||
processed[pos_str] = true
|
processed[pos_str] = true
|
||||||
|
|
||||||
local pos = vector.from_string(pos_str)
|
local pos = vector_from_string(pos_str)
|
||||||
local meta = minetest.get_meta(pos)
|
local meta = get_meta(pos)
|
||||||
|
|
||||||
-- Update node power directly
|
-- Update node power directly
|
||||||
meta:set_int(REDSTONE_POWER_META.."."..source_pos_str, strength)
|
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)
|
get_positions_from_node_rules(pos, "conductor", next_list, powered)
|
||||||
|
|
||||||
-- Update the position
|
-- Update the position
|
||||||
update_sink(pos)
|
update_node(pos)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -156,7 +216,7 @@ vl_scheduler.register_function("vl_redstone:flow_power",function(task, source_po
|
||||||
end)
|
end)
|
||||||
|
|
||||||
function vl_redstone.set_power(pos, strength)
|
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)
|
local distance = meta:get_int(REDSTONE_POWER_META)
|
||||||
|
|
||||||
-- Don't perform an update if the power level is the same as before
|
-- 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
|
end
|
||||||
|
|
||||||
function vl_redstone.get_power_level(pos)
|
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)
|
return meta:get_int(REDSTONE_POWER_META)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue