diff --git a/mods/ITEMS/REDSTONE/mesecons_solarpanel/init.lua b/mods/ITEMS/REDSTONE/mesecons_solarpanel/init.lua index ed0e4c6085..129c28eea9 100644 --- a/mods/ITEMS/REDSTONE/mesecons_solarpanel/init.lua +++ b/mods/ITEMS/REDSTONE/mesecons_solarpanel/init.lua @@ -1,5 +1,69 @@ local S = minetest.get_translator(minetest.get_current_modname()) +local function path_to_sunlight_exists(position, light_level) + local neighbours = { + { x = 0, y = 0, z =-1 }, + { x = 0, y = 0, z = 1 }, + { x = 0, y =-1, z = 0 }, + { x = 0, y = 1, z = 0 }, + { x =-1, y = 0, z = 0 }, + { x = 1, y = 0, z = 0 }, + } + for i=1, #neighbours do + local offset = neighbours[i] + local position_new = vector.add( + position, + offset + ) + local light_level_new = minetest.get_node_light( + position_new, + nil + ) + if 15 == light_level_new then + -- found the sunlight + return true + elseif light_level_new > light_level then + -- search where light is brighter + if path_to_sunlight_exists( + position_new, + light_level_new + ) then + return true + end + end + end +end + +local function sunlight_visible(position) + local light_level + -- Minetest 5.4.0+ can measure the daylight level at a position + if nil ~= minetest.get_natural_light then + light_level = minetest.get_natural_light( + position, + nil + ) + if light_level >= 12 then + return true + end + else -- Minetest 5.3.0 or less can only measure the light level + local time = minetest.get_timeofday() * 24000 + -- only check light level during day + if time > 6000 and time < 18000 then + light_level = minetest.get_node_light( + position, + nil + ) + if light_level >= 12 then + return path_to_sunlight_exists( + position, + 12 + ) + end + end + end + return false +end + local boxes = { -8/16, -8/16, -8/16, 8/16, -2/16, 8/16 } -- Daylight Sensor @@ -95,9 +159,7 @@ minetest.register_abm({ interval = 1, chance = 1, action = function(pos, node, active_object_count, active_object_count_wider) - local light = minetest.get_node_light(pos, nil) - - if light >= 12 and minetest.get_timeofday() > 0.2 and minetest.get_timeofday() < 0.8 then + if sunlight_visible(pos) then minetest.set_node(pos, {name="mesecons_solarpanel:solar_panel_on", param2=node.param2}) mesecon.receptor_on(pos, mesecon.rules.pplate) end @@ -110,9 +172,7 @@ minetest.register_abm({ interval = 1, chance = 1, action = function(pos, node, active_object_count, active_object_count_wider) - local light = minetest.get_node_light(pos, nil) - - if light < 12 then + if not sunlight_visible(pos) then minetest.set_node(pos, {name="mesecons_solarpanel:solar_panel_off", param2=node.param2}) mesecon.receptor_off(pos, mesecon.rules.pplate) end @@ -202,9 +262,7 @@ minetest.register_abm({ interval = 1, chance = 1, action = function(pos, node, active_object_count, active_object_count_wider) - local light = minetest.get_node_light(pos, nil) - - if light < 12 then + if not sunlight_visible(pos) then minetest.set_node(pos, {name="mesecons_solarpanel:solar_panel_inverted_on", param2=node.param2}) mesecon.receptor_on(pos, mesecon.rules.pplate) end @@ -217,9 +275,7 @@ minetest.register_abm({ interval = 1, chance = 1, action = function(pos, node, active_object_count, active_object_count_wider) - local light = minetest.get_node_light(pos, nil) - - if light >= 12 and minetest.get_timeofday() > 0.8 and minetest.get_timeofday() < 0.2 then + if sunlight_visible(pos) then minetest.set_node(pos, {name="mesecons_solarpanel:solar_panel_inverted_off", param2=node.param2}) mesecon.receptor_off(pos, mesecon.rules.pplate) end