From 781ccc04f6d8d7e77b055f42a76bc4c22d5c9126 Mon Sep 17 00:00:00 2001 From: teknomunk Date: Mon, 15 Apr 2024 08:21:14 +0000 Subject: [PATCH] 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 --- mods/ITEMS/REDSTONE/vl_redstone/init.lua | 112 ++++++++++++++--------- 1 file changed, 67 insertions(+), 45 deletions(-) diff --git a/mods/ITEMS/REDSTONE/vl_redstone/init.lua b/mods/ITEMS/REDSTONE/vl_redstone/init.lua index 4d6d0518c..e7b4f4082 100644 --- a/mods/ITEMS/REDSTONE/vl_redstone/init.lua +++ b/mods/ITEMS/REDSTONE/vl_redstone/init.lua @@ -4,10 +4,15 @@ 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 mcl_util_force_get_node = mcl_util.force_get_node +local mcl_util_call_safe = mcl_util.call_safe +local minetest_get_item_group = minetest.get_item_group +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_to_string = vector.to_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_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 node = force_get_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 -- Calculate the maximum power feeding into this node - -- TODO: check how much time this is taking - local meta = minetest.get_meta(pos) + local node_multipower = get_node_multipower_data(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_strength = tonumber(v) - if source_strength > strength then - strength = source_strength - end - end + local sources = node_multipower.sources + for pos_hash,source_strength in pairs(sources) do + --print("\t"..vector_to_string(minetest_get_position_from_hash(pos_hash)).." -> "..tostring(strength)) + if source_strength > strength then strength = source_strength 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 = node_multipower.strength + --print("At "..vector_to_string(pos).." strength="..tostring(strength)..",last_strength="..tostring(last_strength)) if last_strength == strength then return end -- 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 local rule = nil @@ -56,7 +70,7 @@ local function update_node(pos) -- Handle activation local hook = sink.action_on if hook then - call_safe(nil, hook, {pos, node, rule, strength}) + mcl_util_call_safe(nil, hook, {pos, node, rule, strength}) end if sink.onstate then new_node_name = sink.onstate @@ -65,7 +79,7 @@ local function update_node(pos) -- Handle deactivation local hook = sink.action_off if hook then - call_safe(nil, hook, {pos, node, rule, strength}) + mcl_util_call_safe(nil, hook, {pos, node, rule, strength}) end if sink.offstate then new_node_name = sink.offstate @@ -75,7 +89,7 @@ local function update_node(pos) -- TODO: handle signal level change notification local hook = sink.action_change if hook then - call_safe(nil, hook, {pos, node, rule, strength}) + mcl_util_call_safe(nil, hook, {pos, node, rule, strength}) end if sink.strength_state then new_node_name = sink.strength_state[strength] @@ -84,7 +98,7 @@ local function update_node(pos) -- Update the node if new_node_name and new_node_name ~= node.name then node.name = new_node_name - minetest.swap_node(pos, node) + minetest_swap_node(pos, node) end return end @@ -110,9 +124,9 @@ local function update_node(pos) ",conductor.onstate="..tostring(conductor.onstate).. ",conductor.offstate="..tostring(conductor.offstate) ) - ]] + --]] node.name = new_node_name - minetest.swap_node(pos, node) + minetest_swap_node(pos, node) end end end @@ -129,7 +143,7 @@ local POWERED_BLOCK_RULES = { local function get_positions_from_node_rules(pos, rules_type, list, powered) 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 rules if nodedef.mesecons then @@ -143,8 +157,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 get_item_group(node.name,"solid") == 0 then return list end + if not powered[minetest_hash_node_pos(pos)] then return list end + if minetest_get_item_group(node.name,"solid") == 0 then return list end rules = POWERED_BLOCK_RULES end @@ -154,14 +168,14 @@ 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_hash = minetest_hash_node_pos(next_pos) --print("\tnext: "..next_pos_str..", prev="..tostring(list[next_pos_str])) - list[next_pos_str] = true + list[next_pos_hash] = true -- Power solid blocks if rules[i].spread then - powered[next_pos_str] = true - --print("powering "..next_pos_str) + powered[next_pos_hash] = true + --print("powering "..vector_to_string(next_pos) 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") local processed = {} local powered = {} - local source_pos_str = vector_to_string(source_pos) - processed[source_pos_str] = true + local source_pos_hash = minetest_hash_node_pos(source_pos) + processed[source_pos_hash] = true -- Update the source node's redstone power - local meta = get_meta(source_pos) - meta:set_int(REDSTONE_POWER_META, source_strength) + local node_multipower = get_node_multipower_data(source_pos) + node_multipower.strength = source_strength -- Get rules local list = {} @@ -189,17 +203,17 @@ 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_str,dir in pairs(list) do + for pos_hash,dir in pairs(list) do --print("Processing "..pos_str) - if not processed[pos_str] then - processed[pos_str] = true + if not processed[pos_hash] then + processed[pos_hash] = true - local pos = vector_from_string(pos_str) - local meta = get_meta(pos) + local pos = minetest_get_position_from_hash(pos_hash) -- 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)) -- handle spread @@ -216,13 +230,13 @@ vl_scheduler.register_function("vl_redstone:flow_power",function(task, source_po end) function vl_redstone.set_power(pos, strength) - local meta = get_meta(pos) - local distance = meta:get_int(REDSTONE_POWER_META) + local node_multipower = get_node_multipower_data(pos) + local distance = node_multipower.strength or 0 -- Don't perform an update if the power level is the same as before 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 if distance < strength then @@ -234,7 +248,15 @@ function vl_redstone.set_power(pos, strength) end function vl_redstone.get_power_level(pos) - local meta = get_meta(pos) - return meta:get_int(REDSTONE_POWER_META) + local node_multipower = get_node_multipower_data(pos) + return node_multipower.strength or 0 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)