177 lines
5.7 KiB
Lua
177 lines
5.7 KiB
Lua
|
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
|
||
|
})
|