Skip to content

Instantly share code, notes, and snippets.

@sapier
Last active March 9, 2022 00:51
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sapier/7861582 to your computer and use it in GitHub Desktop.
Save sapier/7861582 to your computer and use it in GitHub Desktop.
--------------------------------------------------------------------------------
-- @function [parent=#adv_spawning] check_light_around_voxel
-- @param pos position to validate
-- @param light_around light around definitions
-- @return true/false
--------------------------------------------------------------------------------
function adv_spawning.check_light_around_voxel(pos,light_around)
if light_around == nil then
return true
end
local maxdistance = 0
for i=1,#light_around,1 do
maxdistance = adv_spawning.MAX(maxdistance,light_around[i].distance)
end
local minp = { x=math.floor(pos.x - maxdistance),
y=math.floor(pos.y - maxdistance),
z=math.floor(pos.z - maxdistance)}
local maxp = { x=math.ceil(pos.x + maxdistance),
y=math.ceil(pos.y + maxdistance),
z=math.ceil(pos.z + maxdistance)}
local voxeldata = minetest.get_voxel_manip()
local got_minp,got_maxp = voxeldata:read_from_map(minp,maxp)
local voxel_light_data = voxeldata:get_light_data()
local node_data = voxeldata:get_data()
local voxelhelper = VoxelArea:new(got_minp,got_maxp)
for i=1,#light_around,1 do
for x=pos.x-light_around[i].distance,pos.x+light_around[i].distance,1 do
for y=pos.y-light_around[i].distance,pos.y+light_around[i].distance,1 do
for z=pos.z-light_around[i].distance,pos.z+light_around[i].distance,1 do
local checkpos = { x=x,y=y,z=z}
local time = minetest.get_timeofday()
if light_around[i].type == "TIMED_MIN" or
light_around[i].type == "TIMED_MAX" then
time = light_around[i].time
end
if light_around[i].type == "OVERALL_MIN" or
light_around[i].type == "OVERALL_MAX" then
for j=0,24000,1000 do
local light_level = minetest.get_node_light(checkpos, j)
local voxellight = adv_spawning.voxelmaniplight(node_data,voxel_light_data,voxelhelper,checkpos,j)
if light_level ~= nil then
if light_around[i].type == "OVERALL_MAX" and
light_level > light_around[i].threshold then
return false
end
if light_around[i].type == "OVERALL_MIN" and
light_level < light_around[i].threshold then
return false
end
end
end
else
local light_level = minetest.get_node_light(checkpos, time)
local voxellight = adv_spawning.voxelmaniplight(node_data,voxel_light_data,voxelhelper,checkpos,time)
if light_level ~= nil then
if (light_around[i].type == "TIMED_MIN" or
light_around[i].type == "CURRENT_MIN") and
light_level < light_around[i].threshold then
return false
end
if (light_around[i].type == "TIMED_MAX" or
light_around[i].type == "CURRENT_MAX") and
light_level > light_around[i].threshold then
return false
end
end
end
end
end
end
end
return true
end
local light_lookup = {
{4250+125, 150},
{4500+125, 150},
{4750+125, 250},
{5000+125, 350},
{5250+125, 500},
{5500+125, 675},
{5750+125, 875},
{6000+125, 1000},
{6250+125, 1000}
}
function adv_spawning.day_night_ratio(time)
--make sure time is between 0 and 240000
if time < 0 then
time = time - (((time*-1)/24000)*24000)
end
if time > 24000 then
time = time + ((time/24000)*24000)
end
--invert time for sunset
if time > 12000 then
time = 24000 - time
end
local dnr = 1000
for i=1,#light_lookup,1 do
if time < light_lookup[i][1] then
dnr = light_lookup[i][2]
break
end
end
return dnr
end
function adv_spawning.voxelmaniplight(node_data,light_data,helper,pos,time)
if not helper:containsp(pos) then
minetest.get_node_light(pos, time)
end
local origpos = { x=pos.x, y=pos.y,z=pos.z }
pos = vector.round(pos)
local raw_light_value = light_data[helper:indexp(pos)]
if raw_light_value == nil then
print("Unable to fetch light value: " .. dump(pos))
return 0
end
local light_day = raw_light_value % 16
local light_night = (raw_light_value - light_day)/16
-- check for sunlight_propagates
local raw_node_data = node_data[helper:indexp(pos)]
local nodename = minetest.get_name_from_content_id(raw_node_data)
local nodedef = minetest.registered_nodes[nodename]
if nodedef.sunlight_propagates ~= true then
light_day = 0
light_night = 0
end
if nodedef.light_source ~= nil then
light_day = adv_spawning.MAX(nodedef.light_source,light_day)
light_night = adv_spawning.MAX(nodedef.light_source,light_night)
end
local orig_time = time
time = time *24000
time = time %24000
local dnr = adv_spawning.day_night_ratio(time)
local c = 1000
local current_light = ((dnr * light_day + (c-dnr) * light_night))/c
if(current_light > LIGHT_MAX+1) then
current_light = LIGHT_MAX+1
end
current_light = math.floor(current_light+0.5)
local official_light_value = minetest.get_node_light(origpos, orig_time)
if current_light ~= official_light_value then
local official_node = minetest.get_node(origpos)
print("RAW: " .. dump(raw_light_value) .. " NodeVM: " .. nodename ..
" NodeDirect: " .. official_node.name ..
" VL: " .. current_light .. " ND:" .. dump(official_light_value) ..
" Pos: " .. minetest.pos_to_string(origpos) ..
" Pos rounded: " .. minetest.pos_to_string(pos) ..
" time: " .. time .. " time_orig: " .. orig_time)
end
return current_light
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment