177 lines
5.7 KiB
Lua
Executable File

local function getmp(x)
return (80 * math.floor((x + 32) / 80)) - 32
end
local function get_minp(pos)
return {x=getmp(pos.x), y=getmp(pos.y), z=getmp(pos.z)}
end
--[[local snow_timer = 0
local snow_range = 1
minetest.register_globalstep(function(dtime)
snow_timer = snow_timer + dtime
if snow_timer < 1 then return end
snow_timer = 0
local noise_temperature_raw = minetest.get_perlin(763, 7, 0.5, 512)
local noise_humidity_raw = minetest.get_perlin(834, 7, 0.5, 512)
for _, player in ipairs(minetest.get_connected_players()) do
local pos = player:getpos()
if pos.y > -50 and pos.y < 150 then
--local to_update = {}
--local to_update_index = 1
local minp = get_minp(pos)
local biome_table = get_biome_table(minp, noise_humidity_raw, noise_temperature_raw, snow_range+1)
local vm = minetest.get_voxel_manip()
local eminp, emaxp = vm:read_from_map({x=minp.x-80*snow_range, y=-50, z=minp.z-80*snow_range}, {x=minp.x+79+80*snow_range, y=150, z=minp.z+79+80*snow_range})
--print(dump(eminp), dump(emaxp))
local a = VoxelArea:new{MinEdge=eminp, MaxEdge=emaxp}
local data = vm:get_data()
for i = 1, 80*(snow_range+1)*(snow_range+1) do
local x = math.random(eminp.x, emaxp.x)
local z = math.random(eminp.z, emaxp.z)
local biome = get_nearest_biome(biome_table, x, z)
if biome.t < -0.4 then
local y = emaxp.y
while y >= eminp.y and data[a:index(x, y, z)] == c_air do
y = y - 1
end
if y >= eminp.y and y < emaxp.y then
if data[a:index(x, y, z)] == c_snow then
if minetest.add_node_level({x=x, y=y, z=z}, 7) ~= 0 then
--data[a:index(x, y+1, z)] = c_snow
minetest.set_node({x=x, y=y+1, z=z}, {name = "default:snow"})
end
else
--data[a:index(x, y+1, z)] = c_snow
minetest.set_node({x=x, y=y+1, z=z}, {name = "default:snow"})
end
--to_update[to_update_index] = {x=x,y=y+1,z=z}
--to_update_index = to_update_index+1
end
end
end
--vm:set_data(data)
--vm:write_to_map(data)
--for _, pos in ipairs(to_update) do
-- nodeupdate(pos)
--end
end
end
end)]]
local function add_snow_level(pos)
local level = minetest.get_node_level(pos)
if level <= 28 then
minetest.add_node_level(pos, 7)
return 0
else
return 7
end
end
local is_snowing = false
local to_snow = {}
local to_snow_index = 0
local SNOW_RANGE = 16
local SNOW_BLOCK_SIZE = 4
local SNOW_STEPS = 10
local SNOW_TIMES_PER_BLOCK = 4
minetest.register_globalstep(function(dtime)
if math.random(1, 5000) == 1 then
is_snowing = not is_snowing
end
if to_snow_index == 0 then
if is_snowing then
for _, player in ipairs(minetest.get_connected_players()) do
local pos = player:getpos()
if pos.y > -50 and pos.y < 150 then
local x = SNOW_BLOCK_SIZE*math.floor((pos.x/SNOW_BLOCK_SIZE)+0.5)
local z = SNOW_BLOCK_SIZE*math.floor((pos.z/SNOW_BLOCK_SIZE)+0.5)
for xi = -SNOW_RANGE, SNOW_RANGE do
for zi = -SNOW_RANGE, SNOW_RANGE do
to_snow_index = to_snow_index + 1
to_snow[to_snow_index] = {x=x+SNOW_BLOCK_SIZE*xi, y=0, z=z+SNOW_BLOCK_SIZE*zi}
end
end
end
end
end
else
local noise_temperature_raw = minetest.get_perlin(763, 7, 0.5, 512)
local noise_humidity_raw = minetest.get_perlin(834, 7, 0.5, 512)
for s = 1, math.min(SNOW_STEPS, to_snow_index) do
local pos = to_snow[to_snow_index]
--print(dump(pos))
to_snow[to_snow_index] = nil
to_snow_index = to_snow_index - 1
local minp = get_minp(pos)
local biome_table = get_biome_table(minp, noise_humidity_raw, noise_temperature_raw)
local vm = minetest.get_voxel_manip()
local eminp, emaxp = vm:read_from_map({x=pos.x, y=-50, z=pos.z}, {x=pos.x + SNOW_BLOCK_SIZE - 1, y=150, z=pos.z + SNOW_BLOCK_SIZE - 1})
--print(eminp.y, emaxp.y)
--print(dump(eminp),dump(emaxp))
local a = VoxelArea:new{MinEdge=eminp, MaxEdge=emaxp}
local data = vm:get_data()
for i = 1, SNOW_TIMES_PER_BLOCK do
local x = math.random(pos.x, pos.x + SNOW_BLOCK_SIZE - 1)
local z = math.random(pos.z, pos.z + SNOW_BLOCK_SIZE - 1)
local biome = get_nearest_biome(biome_table, x, z)
if biome.t < -0.4 then
local y = emaxp.y
while y >= eminp.y and (data[a:index(x, y, z)] == c_air or data[a:index(x, y, z)] == c_ignore) do
y = y - 1
end
if y >= eminp.y and y < emaxp.y then
if data[a:index(x, y, z)] == c_snow then
--if minetest.add_node_level({x=x, y=y, z=z}, 7) ~= 0 then
if add_snow_level({x=x, y=y, z=z}) ~= 0 then
-- do nothing, max stack
--minetest.set_node({x=x, y=y, z=z}, {name = "default:snowblock"})
end
elseif data[a:index(x, y, z)] == c_snowblock or data[a:index(x, y, z)] == c_water then
-- do nothing
else
minetest.set_node({x=x, y=y+1, z=z}, {name = "default:snow"})
end
end
end
end
end
end
end)
minetest.register_abm({
nodenames = {"mg:pineleaves"},
interval = 2,
chance = 4,
action = function(pos, node)
local above = {x=pos.x, y=pos.y+1, z=pos.z}
if minetest.get_node(above).name == "default:snow" then
local level = minetest.get_node_level(above)
if level >= 14 then
for i = 1, 15 do
local p = {x=pos.x, y=pos.y-i, z=pos.z}
local n = minetest.get_node(p).name
if n ~= "air" and n ~= "mg:pineleaves" then
if n == "default:snow" then
--if minetest.add_node_level(p, 7) == 0 then
if add_snow_level(p) == 0 then
minetest.add_node_level(above, -7)
end
else
local above_p = {x=p.x, y=p.y+1, z=p.z}
if minetest.get_node(above_p).name == "air" then
minetest.set_node(above_p, {name = "default:snow"})
minetest.add_node_level(above, -7)
end
end
return
end
end
end
end
end
})