local worldpath = minetest.get_worldpath() local network_filename = worldpath.."/waterworks_network.json" -- Json storage local save_data = function() if waterworks.dirty_data ~= true then return end local file = io.open(network_filename, "w") if file then file:write(minetest.serialize(waterworks.pipe_networks)) file:close() waterworks.dirty_data = false end end local read_data = function() local file = io.open(network_filename, "r") if file then waterworks.pipe_networks = minetest.deserialize(file:read("*all")) -- note: any cached references to pipe_networks is invalidated here, so do this once at the beginning of the run and never again thereafter. file:close() else waterworks.pipe_networks = {} end waterworks.dirty_data = false for _, net in ipairs(waterworks.pipe_networks) do net.cache_valid = false end end read_data() ---------------------------------------------- local nets_near_players = {} minetest.register_abm ({ label = "Active connected node tracking", nodenames = {"group:waterworks_connected"}, interval = 1.0, chance = 1, action = function(pos, node, active_object_count, active_object_count_wider) local player_close = false for _, player in ipairs(minetest.get_connected_players()) do local player_pos = player:get_pos() if math.abs(player_pos.x - pos.x) < 161 and math.abs(player_pos.z - pos.z) < 161 and math.abs(player_pos.y - pos.y) < 161 then player_close = true break end end if not player_close then return end local hash = minetest.hash_node_position(pos) + waterworks.facedir_to_hash(node.param2) local net_index = waterworks.find_network_for_pipe_hash(hash) if net_index < 0 then return end --minetest.chat_send_all("net near player " .. tostring(net_index)) nets_near_players[net_index] = 5.0 end, }) local forceloads = {} local timer = 0 minetest.register_globalstep(function(dtime) timer = timer + dtime if timer > 1.0 then if waterworks.dirty_data then -- it's possible that a pipe network was split or merged, invalidating the nets_near_players values here. -- Best to clear them and do nothing for one globalstep, they'll be repopulated shortly. nets_near_players = {} end -- find connected node positions for all networks with connected nodes near players local ensure_forceload = {} for index, live_time in pairs(nets_near_players) do local new_time = live_time - timer --minetest.chat_send_all("new time " .. tostring(new_time)) if new_time < 0 then nets_near_players[index] = nil else nets_near_players[index] = new_time for connection_type, connections in pairs(waterworks.pipe_networks[index].connected) do for hash, _ in pairs(connections) do ensure_forceload[hash] = true end end end end -- clear forceloads that are no longer needed for hash, _ in pairs(forceloads) do if not ensure_forceload[hash] then minetest.forceload_free_block(minetest.get_position_from_hash(hash), true) end end forceloads = ensure_forceload -- enable forceloads that are needed for hash, _ in pairs(forceloads) do minetest.forceload_block(minetest.get_position_from_hash(hash), true) end timer = timer - 1.0 save_data() for index, _ in pairs(nets_near_players) do --minetest.chat_send_all("executing index " .. tostring(index)) waterworks.execute_pipes(index, 8) end end end)