mirror of
https://git.minetest.land/VoxeLibre/VoxeLibre.git
synced 2024-11-30 22:41:20 +01:00
Convert from storing power information directly in node metadata to storing in memory in a multipower table that gets loaded and saved to node metadata as needed, change all locally cached functions to have the source prefix in the name for better core readability, fix global access in mcl_util.assign_uuid
This commit is contained in:
parent
6396b6f56c
commit
781ccc04f6
1 changed files with 67 additions and 45 deletions
|
@ -4,10 +4,15 @@ vl_redstone = {}
|
||||||
local mod = vl_redstone
|
local mod = vl_redstone
|
||||||
|
|
||||||
-- Imports
|
-- Imports
|
||||||
local force_get_node = mcl_util.force_get_node
|
local mcl_util_force_get_node = mcl_util.force_get_node
|
||||||
local call_safe = mcl_util.call_safe
|
local mcl_util_call_safe = mcl_util.call_safe
|
||||||
local get_item_group = minetest.get_item_group
|
local minetest_get_item_group = minetest.get_item_group
|
||||||
local get_meta = minetest.get_meta
|
local minetest_get_meta = minetest.get_meta
|
||||||
|
local minetest_hash_node_pos = minetest.hash_node_position
|
||||||
|
local minetest_get_position_from_hash = minetest.get_position_from_hash
|
||||||
|
local minetest_serialize = minetest.serialize
|
||||||
|
local minetest_deserialize = minetest.deserialize
|
||||||
|
local minetest_swap_node = minetest.swap_node
|
||||||
local vector_add = vector.add
|
local vector_add = vector.add
|
||||||
local vector_to_string = vector.to_string
|
local vector_to_string = vector.to_string
|
||||||
local vector_from_string = vector.from_string
|
local vector_from_string = vector.from_string
|
||||||
|
@ -16,33 +21,42 @@ local vector_from_string = vector.from_string
|
||||||
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 multipower_cache = {}
|
||||||
|
|
||||||
|
local function get_node_multipower_data(pos)
|
||||||
|
local hash = minetest_hash_node_pos(pos)
|
||||||
|
local node_multipower = multipower_cache[hash]
|
||||||
|
if not node_multipower then
|
||||||
|
local meta = minetest_get_meta(pos)
|
||||||
|
node_multipower = minetest_deserialize(meta:get_string("vl_redstone.multipower")) or {sources={}}
|
||||||
|
multipower_cache[hash] = node_multipower
|
||||||
|
end
|
||||||
|
return node_multipower
|
||||||
|
end
|
||||||
|
|
||||||
local function update_node(pos)
|
local function update_node(pos)
|
||||||
local node = force_get_node(pos)
|
local node = mcl_util_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
|
||||||
|
|
||||||
-- 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 node_multipower = get_node_multipower_data(pos)
|
||||||
local meta = minetest.get_meta(pos)
|
|
||||||
local strength = 0
|
local strength = 0
|
||||||
local meta_tbl = meta:to_table()
|
local sources = node_multipower.sources
|
||||||
for k,v in pairs(meta_tbl.fields) do
|
for pos_hash,source_strength in pairs(sources) do
|
||||||
if string.sub(k,1,#REDSTONE_POWER_META_SOURCE) == REDSTONE_POWER_META_SOURCE then
|
--print("\t"..vector_to_string(minetest_get_position_from_hash(pos_hash)).." -> "..tostring(strength))
|
||||||
local source_strength = tonumber(v)
|
if source_strength > strength then strength = source_strength end
|
||||||
if source_strength > strength then
|
|
||||||
strength = source_strength
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Don't do any processing inf the actual strength at this node has changed
|
-- 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 = node_multipower.strength
|
||||||
|
--print("At "..vector_to_string(pos).." strength="..tostring(strength)..",last_strength="..tostring(last_strength))
|
||||||
if last_strength == strength then return end
|
if last_strength == strength then return end
|
||||||
|
|
||||||
-- Update the state
|
-- Update the state
|
||||||
meta:set_int(REDSTONE_POWER_META, strength)
|
node_multipower.strength = strength
|
||||||
|
|
||||||
-- TODO: determine the input rule that the strength is coming from
|
-- TODO: determine the input rule that the strength is coming from
|
||||||
local rule = nil
|
local rule = nil
|
||||||
|
@ -56,7 +70,7 @@ local function update_node(pos)
|
||||||
-- Handle activation
|
-- Handle activation
|
||||||
local hook = sink.action_on
|
local hook = sink.action_on
|
||||||
if hook then
|
if hook then
|
||||||
call_safe(nil, hook, {pos, node, rule, strength})
|
mcl_util_call_safe(nil, hook, {pos, node, rule, strength})
|
||||||
end
|
end
|
||||||
if sink.onstate then
|
if sink.onstate then
|
||||||
new_node_name = sink.onstate
|
new_node_name = sink.onstate
|
||||||
|
@ -65,7 +79,7 @@ local function update_node(pos)
|
||||||
-- Handle deactivation
|
-- Handle deactivation
|
||||||
local hook = sink.action_off
|
local hook = sink.action_off
|
||||||
if hook then
|
if hook then
|
||||||
call_safe(nil, hook, {pos, node, rule, strength})
|
mcl_util_call_safe(nil, hook, {pos, node, rule, strength})
|
||||||
end
|
end
|
||||||
if sink.offstate then
|
if sink.offstate then
|
||||||
new_node_name = sink.offstate
|
new_node_name = sink.offstate
|
||||||
|
@ -75,7 +89,7 @@ local function update_node(pos)
|
||||||
-- TODO: handle signal level change notification
|
-- TODO: handle signal level change notification
|
||||||
local hook = sink.action_change
|
local hook = sink.action_change
|
||||||
if hook then
|
if hook then
|
||||||
call_safe(nil, hook, {pos, node, rule, strength})
|
mcl_util_call_safe(nil, hook, {pos, node, rule, strength})
|
||||||
end
|
end
|
||||||
if sink.strength_state then
|
if sink.strength_state then
|
||||||
new_node_name = sink.strength_state[strength]
|
new_node_name = sink.strength_state[strength]
|
||||||
|
@ -84,7 +98,7 @@ local function update_node(pos)
|
||||||
-- Update the node
|
-- Update the node
|
||||||
if new_node_name and new_node_name ~= node.name then
|
if new_node_name and new_node_name ~= node.name then
|
||||||
node.name = new_node_name
|
node.name = new_node_name
|
||||||
minetest.swap_node(pos, node)
|
minetest_swap_node(pos, node)
|
||||||
end
|
end
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
@ -110,9 +124,9 @@ local function update_node(pos)
|
||||||
",conductor.onstate="..tostring(conductor.onstate)..
|
",conductor.onstate="..tostring(conductor.onstate)..
|
||||||
",conductor.offstate="..tostring(conductor.offstate)
|
",conductor.offstate="..tostring(conductor.offstate)
|
||||||
)
|
)
|
||||||
]]
|
--]]
|
||||||
node.name = new_node_name
|
node.name = new_node_name
|
||||||
minetest.swap_node(pos, node)
|
minetest_swap_node(pos, node)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -129,7 +143,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 = force_get_node(pos)
|
local node = mcl_util_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
|
||||||
|
@ -143,8 +157,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[minetest_hash_node_pos(pos)] then return list end
|
||||||
if get_item_group(node.name,"solid") == 0 then return list end
|
if minetest_get_item_group(node.name,"solid") == 0 then return list end
|
||||||
|
|
||||||
rules = POWERED_BLOCK_RULES
|
rules = POWERED_BLOCK_RULES
|
||||||
end
|
end
|
||||||
|
@ -154,14 +168,14 @@ 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_hash = minetest_hash_node_pos(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_hash] = true
|
||||||
|
|
||||||
-- Power solid blocks
|
-- Power solid blocks
|
||||||
if rules[i].spread then
|
if rules[i].spread then
|
||||||
powered[next_pos_str] = true
|
powered[next_pos_hash] = true
|
||||||
--print("powering "..next_pos_str)
|
--print("powering "..vector_to_string(next_pos)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -172,12 +186,12 @@ vl_scheduler.register_function("vl_redstone:flow_power",function(task, source_po
|
||||||
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_hash = minetest_hash_node_pos(source_pos)
|
||||||
processed[source_pos_str] = true
|
processed[source_pos_hash] = true
|
||||||
|
|
||||||
-- Update the source node's redstone power
|
-- Update the source node's redstone power
|
||||||
local meta = get_meta(source_pos)
|
local node_multipower = get_node_multipower_data(source_pos)
|
||||||
meta:set_int(REDSTONE_POWER_META, source_strength)
|
node_multipower.strength = source_strength
|
||||||
|
|
||||||
-- Get rules
|
-- Get rules
|
||||||
local list = {}
|
local list = {}
|
||||||
|
@ -189,17 +203,17 @@ vl_scheduler.register_function("vl_redstone:flow_power",function(task, source_po
|
||||||
local strength = source_strength - (i - 1)
|
local strength = source_strength - (i - 1)
|
||||||
if strength < 0 then strength = 0 end
|
if strength < 0 then strength = 0 end
|
||||||
|
|
||||||
for pos_str,dir in pairs(list) do
|
for pos_hash,dir in pairs(list) do
|
||||||
--print("Processing "..pos_str)
|
--print("Processing "..pos_str)
|
||||||
|
|
||||||
if not processed[pos_str] then
|
if not processed[pos_hash] then
|
||||||
processed[pos_str] = true
|
processed[pos_hash] = true
|
||||||
|
|
||||||
local pos = vector_from_string(pos_str)
|
local pos = minetest_get_position_from_hash(pos_hash)
|
||||||
local meta = get_meta(pos)
|
|
||||||
|
|
||||||
-- Update node power directly
|
-- Update node power directly
|
||||||
meta:set_int(REDSTONE_POWER_META.."."..source_pos_str, strength)
|
local node_multipower = get_node_multipower_data(pos)
|
||||||
|
node_multipower.sources[source_pos_hash] = strength
|
||||||
--print("pos="..vector.to_string(pos)..", strength="..tostring(strength))
|
--print("pos="..vector.to_string(pos)..", strength="..tostring(strength))
|
||||||
|
|
||||||
-- handle spread
|
-- handle spread
|
||||||
|
@ -216,13 +230,13 @@ 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 = get_meta(pos)
|
local node_multipower = get_node_multipower_data(pos)
|
||||||
local distance = meta:get_int(REDSTONE_POWER_META)
|
local distance = node_multipower.strength or 0
|
||||||
|
|
||||||
-- 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
|
||||||
if distance == strength then return end
|
if distance == strength then return end
|
||||||
|
|
||||||
print("previous="..tostring(distance)..", new="..tostring(strength))
|
--print("previous="..tostring(distance)..", new="..tostring(strength))
|
||||||
|
|
||||||
-- Make the update distance the maximum of the new strength and the old strength
|
-- Make the update distance the maximum of the new strength and the old strength
|
||||||
if distance < strength then
|
if distance < strength then
|
||||||
|
@ -234,7 +248,15 @@ 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 = get_meta(pos)
|
local node_multipower = get_node_multipower_data(pos)
|
||||||
return meta:get_int(REDSTONE_POWER_META)
|
return node_multipower.strength or 0
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Persist multipower data
|
||||||
|
minetest.register_on_shutdown(function()
|
||||||
|
for pos_hash,node_multipower in pairs(multipower_cache) do
|
||||||
|
local pos = minetest_get_position_from_hash(pos_hash)
|
||||||
|
local meta = minetest_get_meta(pos)
|
||||||
|
meta:set_string("vl_redstone.multipower", minetest_serialize(node_multipower))
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
Loading…
Reference in a new issue