mirror of
https://git.minetest.land/VoxeLibre/VoxeLibre.git
synced 2024-11-27 21:11:05 +01:00
Fix crash in comparitor code, add input rule processing
This commit is contained in:
parent
74d3fff5ff
commit
1da30698d7
2 changed files with 138 additions and 27 deletions
|
@ -100,6 +100,8 @@ end
|
|||
|
||||
function mod.read_inventory(inv, inv_name)
|
||||
local stacks = inv:get_list(inv_name)
|
||||
if not stacks then return 0 end
|
||||
|
||||
local count = 0
|
||||
for i=1,#stacks do
|
||||
count = count + ( stacks[i]:get_count() / stacks[i]:get_stack_max() )
|
||||
|
|
|
@ -16,6 +16,7 @@ local minetest_swap_node = minetest.swap_node
|
|||
local vector_add = vector.add
|
||||
local vector_to_string = vector.to_string
|
||||
local vector_from_string = vector.from_string
|
||||
local math_floor = math.floor
|
||||
|
||||
-- Constants
|
||||
local REDSTONE_POWER_META = modname .. ".power"
|
||||
|
@ -23,46 +24,145 @@ local REDSTONE_POWER_META_SOURCE = REDSTONE_POWER_META.."."
|
|||
|
||||
local multipower_cache = {}
|
||||
|
||||
local function hash_from_direction(dir)
|
||||
return 9 * (dir.x + 1) + 3 * (dir.y + 1) + dir.z + 1
|
||||
end
|
||||
local function direction_from_hash(dir_hash)
|
||||
local x = math_floor(dir_hash / 9) - 1
|
||||
local y = math_floor((dir_hash % 9) / 3 ) - 1
|
||||
local z = dir_hash % 3 - 1
|
||||
return vector.new(x,y,z)
|
||||
end
|
||||
local DIR_HASH_ZERO = hash_from_direction(vector.zero())
|
||||
print("DIR_HASH_ZERO="..tostring(DIR_HASH_ZERO))
|
||||
|
||||
local function get_input_rules_hash(mesecons, input_rules)
|
||||
-- Skip build if already built
|
||||
local redstone = mesecons._vl_redtone or {}
|
||||
mesecons._vl_redstone = redstone
|
||||
if redstone.input_rules_hash then return redstone.input_rules_hash end
|
||||
|
||||
-- Build the rules
|
||||
local input_rules_hash = {}
|
||||
redstone.input_rules_hash = input_rules_hash
|
||||
for i=1,#input_rules do
|
||||
input_rules_hash[hash_from_direction(input_rules[i])] = true
|
||||
end
|
||||
|
||||
return input_rules_hash
|
||||
end
|
||||
|
||||
local function get_node_multipower_data(pos, no_create)
|
||||
local hash = minetest_hash_node_pos(pos)
|
||||
local node_multipower = multipower_cache[hash]
|
||||
if not node_multipower and not no_create then
|
||||
local meta = minetest_get_meta(pos)
|
||||
node_multipower = minetest_deserialize(meta:get_string("vl_redstone.multipower")) or {sources={}}
|
||||
node_multipower = minetest_deserialize(meta:get_string("vl_redstone.multipower"))
|
||||
if not node_multipower or node_multipower.version ~= 1 then
|
||||
node_multipower = {
|
||||
version = 1,
|
||||
sources={}
|
||||
}
|
||||
end
|
||||
multipower_cache[hash] = node_multipower
|
||||
end
|
||||
return node_multipower
|
||||
end
|
||||
|
||||
local function calculate_driven_strength(pos, input_rules_hash)
|
||||
local dir_hash = dir and hash_from_direction(dir)
|
||||
local node_multipower = get_node_multipower_data(pos)
|
||||
local strength = 0
|
||||
local strongest_direction_hash = nil
|
||||
local sources = node_multipower.sources
|
||||
input_rules_hash = input_rules_hash or {}
|
||||
|
||||
print("in update_node(pos="..vector_to_string(pos)..") node_multipower("..tostring(node_multipower)..")="..dump(node_multipower))
|
||||
for pos_hash,data in pairs(sources) do
|
||||
local source_strength = data[1]
|
||||
local dirs = data[2]
|
||||
--print("data="..dump(data))
|
||||
--print("\t"..vector_to_string(pos)..".source["..vector_to_string(minetest_get_position_from_hash(pos_hash)).."] = "..tostring(strength))
|
||||
|
||||
-- Filter by specified direction
|
||||
local match = false
|
||||
if not dir_hash then
|
||||
match = true
|
||||
else
|
||||
for i=1,#dirs do
|
||||
match = match or input_rules_hash[dirs[i]]
|
||||
end
|
||||
end
|
||||
|
||||
print("match="..tostring(match)..",source_strength="..tostring(source_strength))
|
||||
|
||||
-- Update strength and track which direction the strongest power is coming from
|
||||
if match and source_strength >= strength then
|
||||
strength = source_strength
|
||||
if #dirs ~= 0 then
|
||||
strongest_direction_hash = dirs[1]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return strength,strongest_direction_hash
|
||||
end
|
||||
|
||||
local function update_node(pos)
|
||||
local node = mcl_util_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
|
||||
-- Only do this processing of signal sinks and conductors
|
||||
local nodedef_mesecons = nodedef.mesecons
|
||||
if not nodedef_mesecons then return end
|
||||
|
||||
-- Calculate the maximum power feeding into this node
|
||||
local node_multipower = get_node_multipower_data(pos)
|
||||
local strength = 0
|
||||
local sources = node_multipower.sources
|
||||
--print("in update_node(pos="..vector_to_string(pos)..") node_multipower("..tostring(node_multipower)..")="..dump(node_multipower))
|
||||
for pos_hash,source_strength in pairs(sources) do
|
||||
--print("\t"..vector_to_string(pos)..".source["..vector_to_string(minetest_get_position_from_hash(pos_hash)).."] = "..tostring(strength))
|
||||
if source_strength > strength then strength = source_strength end
|
||||
print("Running update_node(pos="..vector_to_string(pos)..")")
|
||||
|
||||
-- Get input rules
|
||||
local input_rules = nil
|
||||
if nodedef_mesecons.conductor then
|
||||
input_rules = nodedef_mesecons.conductor.rules
|
||||
elseif nodedef_mesecons.effector then
|
||||
input_rules = nodedef_mesecons.effector.rules
|
||||
else
|
||||
-- No input rules, can't act
|
||||
print("Unable to find input rules for "..node.name..": mesecons="..dump(nodedef_mesecons))
|
||||
return
|
||||
end
|
||||
|
||||
-- Calculate the maximum power feeding into this node
|
||||
local input_rules_hash = get_input_rules_hash(nodedef_mesecons, input_rules)
|
||||
print("input_rules_hash="..dump(input_rules_hash)..", input_rules="..dump(input_rules))
|
||||
local strength,dir_hash = calculate_driven_strength(pos, input_rules_hash)
|
||||
print("strength="..tostring(strength)..",dir_hash="..tostring(dir_hash))
|
||||
|
||||
-- Don't do any processing inf the actual strength at this node has changed
|
||||
local node_multipower = get_node_multipower_data(pos)
|
||||
local last_strength = node_multipower.strength or 0
|
||||
--print("At "..vector_to_string(pos).." strength="..tostring(strength)..",last_strength="..tostring(last_strength))
|
||||
print("At "..vector_to_string(pos).." strength="..tostring(strength)..",last_strength="..tostring(last_strength))
|
||||
if last_strength == strength then return end
|
||||
|
||||
-- Determine the input rule that the strength is coming from (for mesecons compatibility; there are mods that depend on it)
|
||||
local rule = nil
|
||||
for i = 1,#input_rules do
|
||||
local input_rule = input_rules[i]
|
||||
local input_rule_hash = hash_from_direction(input_rule)
|
||||
if dir_hash == input_rule_hash then
|
||||
rule = input_rule
|
||||
break
|
||||
end
|
||||
end
|
||||
if not rule then
|
||||
print("No rule found")
|
||||
return
|
||||
else
|
||||
print("rule="..dump(rule))
|
||||
end
|
||||
|
||||
-- Update the state
|
||||
node_multipower.strength = strength
|
||||
|
||||
-- TODO: determine the input rule that the strength is coming from (for mesecons compatibility; there are mods that depend on it)
|
||||
local rule = nil
|
||||
|
||||
local sink = nodedef.mesecons.effector
|
||||
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)..")")
|
||||
|
@ -87,7 +187,7 @@ local function update_node(pos)
|
|||
end
|
||||
end
|
||||
|
||||
-- TODO: handle signal level change notification
|
||||
-- handle signal level change notification
|
||||
local hook = sink.action_change
|
||||
if hook then
|
||||
mcl_util_call_safe(nil, hook, {pos, node, rule, strength})
|
||||
|
@ -104,7 +204,7 @@ local function update_node(pos)
|
|||
return
|
||||
end
|
||||
|
||||
local conductor = nodedef.mesecons.conductor
|
||||
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
|
||||
|
@ -118,7 +218,7 @@ local function update_node(pos)
|
|||
|
||||
-- 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..
|
||||
|
@ -169,10 +269,13 @@ 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 rule = rules[i]
|
||||
local next_pos = vector_add(pos, rule)
|
||||
local next_pos_hash = minetest_hash_node_pos(next_pos)
|
||||
--print("\tnext: "..next_pos_str..", prev="..tostring(list[next_pos_str]))
|
||||
list[next_pos_hash] = true
|
||||
local dirs = list[next_pos_hash] or {}
|
||||
list[next_pos_hash] = dirs
|
||||
dirs[hash_from_direction(rule)] = true
|
||||
|
||||
-- Power solid blocks
|
||||
if rules[i].spread then
|
||||
|
@ -206,7 +309,7 @@ vl_scheduler.register_function("vl_redstone:flow_power",function(task, source_po
|
|||
local strength = source_strength - (i - 1)
|
||||
if strength < 0 then strength = 0 end
|
||||
|
||||
for pos_hash,dir in pairs(list) do
|
||||
for pos_hash,dir_list in pairs(list) do
|
||||
--print("Processing "..pos_str)
|
||||
|
||||
if not processed[pos_hash] then
|
||||
|
@ -216,11 +319,17 @@ vl_scheduler.register_function("vl_redstone:flow_power",function(task, source_po
|
|||
|
||||
-- Update node power directly
|
||||
local node_multipower = get_node_multipower_data(pos)
|
||||
--local old_strength = node_multipower.sources[source_pos_hash] or 0
|
||||
--print("Changing "..vector.to_string(pos)..".source["..vector_to_string(source_pos).."] from "..tostring(old_strength).." to "..tostring(strength))
|
||||
--print("\tBefore node_multipower("..tostring(node_multipower)..")="..dump(node_multipower))
|
||||
node_multipower.sources[source_pos_hash] = strength
|
||||
--print("\tAfter node_multipower("..tostring(node_multipower)..")="..dump(node_multipower))
|
||||
local old_data = node_multipower.sources[source_pos_hash]
|
||||
local old_strength = old_data and old_data[1] or 0
|
||||
print("Changing "..vector.to_string(pos)..".source["..vector_to_string(source_pos).."] from "..tostring(old_strength).." to "..tostring(strength))
|
||||
print("\tBefore node_multipower("..tostring(node_multipower)..")="..dump(node_multipower))
|
||||
print("\tdir_list="..dump(dir_list))
|
||||
local dirs = {}
|
||||
for k,_ in pairs(dir_list) do
|
||||
dirs[#dirs+1] = k
|
||||
end
|
||||
node_multipower.sources[source_pos_hash] = {strength,dirs}
|
||||
print("\tAfter node_multipower("..tostring(node_multipower)..")="..dump(node_multipower))
|
||||
|
||||
-- handle spread
|
||||
get_positions_from_node_rules(pos, "conductor", next_list, powered)
|
||||
|
|
Loading…
Reference in a new issue