2021-03-01 18:36:01 +01:00

264 lines
6.3 KiB
Lua

local load_time_start = os.clock()
local ast_hdif_max = 3
local function log(msg)
print("[sun_flowers] " .. msg)
end
local function stem(h, pr)
local tab,n = {{0,h-1,0}},2
local ast = 1
for y = 0,h-2 do
tab[n] = {0,y,0}
n = n+1
if ast ~= ast_hdif_max
and pr:next(1,ast) == 1 then
for i = -1,1,2 do
for _,crd in pairs({
{i,0},
{0,i},
}) do
if pr:next(1,3) == 1 then
tab[n] = {crd[1],y,crd[2]}
n = n+1
end
end
ast = ast_hdif_max
end
else
ast = ast-1
end
end
return tab--,n
end
--[[ used before doors update
local to_meta,num = {},1
local function do_metas(tag)
local state = tag and 0 or 1
for _,pos in pairs(to_meta) do
minetest.get_meta(pos):set_int("state", state)
end
to_meta,num = {},1
end
local function panel_meta(pos)
to_meta[num] = pos
num = num+1
end--]]
local c_air = minetest.get_content_id("air")
local c_ignore = minetest.get_content_id("ignore")
local c_stengl = minetest.get_content_id("default:fence_wood")
local c_stempel_tag = minetest.get_content_id("mesecons_solarpanel:solar_panel_on")
local c_stempel_nacht = minetest.get_content_id("mesecons_solarpanel:solar_panel_off")
local c_blutenblatt = minetest.get_content_id("doors:trapdoor_open")
local c_blutenblatt_geschlossen = minetest.get_content_id("doors:trapdoor")
--local param2ps_list = {[0]={-1,0}, {0,-1}, {1,0}, {0,1}}
local param2ps_list = {[10]={-1,0}, [19]={0,-1}, [4]={1,0}, [13]={0,1}}
local function make_flower(h, pr, area, data, param2s, shine, pz,py,px)
for _,crd in pairs(stem(h, pr)) do
local z,y,x = unpack(crd)
local vi = area:index(px+x, py+y, pz+z)
if data[vi] == c_air
or data[vi] == c_ignore then
data[vi] = c_stengl
end
end
local blutenblatt, stempel
if shine then
blutenblatt = c_blutenblatt
stempel = c_stempel_tag
else
blutenblatt = c_blutenblatt_geschlossen
stempel = c_stempel_nacht
end
local y = py+h
for par,crd in pairs(param2ps_list) do
local z = pz+crd[1]
local x = px+crd[2]
local vi = area:index(x, y, z)
if data[vi] == c_air
or data[vi] == c_ignore then
data[vi] = blutenblatt
param2s[vi] = par
--panel_meta({x=x,y=y,z=z})
end
end
local vi = area:index(px, y, pz)
if data[vi] == c_air
or data[vi] == c_ignore then
data[vi] = stempel
param2s[vi] = 1
end
end
-- nicht zum generieren verwenden
local function spawn_flower(pos)
local t1 = os.clock()
local pr = PseudoRandom(pos.x+pos.y*3+pos.z*5+463)
local h = pr:next(3,7)
--local tag = minetest.get_node_light(pos) >= 12
local tag = math.abs(minetest.get_timeofday()-0.5) < 0.25
local manip = minetest.get_voxel_manip()
local emerged_pos1, emerged_pos2 = manip:read_from_map({x=pos.x-1, y=pos.y, z=pos.z-1},
{x=pos.x+1, y=pos.y+h, z=pos.z+1})
local area = VoxelArea:new({MinEdge=emerged_pos1, MaxEdge=emerged_pos2})
local nodes = manip:get_data()
local param2s = manip:get_param2_data()
make_flower(h, pr, area, nodes, param2s, tag, pos.z,pos.y,pos.x)
manip:set_data(nodes)
manip:set_param2_data(param2s)
manip:write_to_map()
log("flower grew", 2, t1)
--[[
t1 = os.clock()
do_metas(tag)
log("metas set", 2, t1)--]]
t1 = os.clock()
manip:update_map()
log("map updated", 2, t1)
end
minetest.register_node("sun_flowers:spawner", {
node_placement_prediction = "",
tiles = {"default_furnace_fire_fg.png"},
inventory_image = "default_sapling.png^default_furnace_fire_fg.png",
stack_max = 1024,
groups = {snappy=2,dig_immediate=3},
sounds = default.node_sound_leaves_defaults(),
on_construct = function(pos)
spawn_flower(pos)
end,
})
--mapgen
local function soil_node(id)
local name = minetest.get_name_from_content_id(id)
local def = minetest.registered_nodes[name]
if not def
or not def.groups
or def.groups.soil ~= 1
or not string.find(name, "grass") then
return false
end
return true
end
local soils = {}
local function is_soil(id)
local soil = soils[id]
if soil ~= nil then
return soil
end
soil = soil_node(id)
soils[id] = soil
return soil
end
local perlinmap
minetest.register_on_generated(function(minp, maxp, seed)
--avoid calculating perlin noises for unneeded places
if maxp.y <= -6
or minp.y >= 150 then
return
end
local t1 = os.clock()
local x0,z0,x1 = minp.x,minp.z,maxp.x
-- Assume X and Z lengths are equal
local divs = (x1-x0)
if not perlinmap then
perlinmap = minetest.get_perlin_map({
offset = 0,
scale = 1,
seed = 4213,
octaves = 3,
persist = 0.6,
spread = {x=100, y=100, z=100},
}, {x=divs+1, y=divs+1, z=1})
end
local tag = math.abs(minetest.get_timeofday()-0.5) < 0.25
local pr = PseudoRandom(seed+42)
local vm, area, data, param2s, pmap
local heightmap = minetest.get_mapgen_object("heightmap")
if not heightmap then
return
end
local hmi = 1
local flower_placed = false
for j=0,divs do
for i=0,divs do
local x,z = x0+i,z0+j
if (x+z)%2 == 0 -- chess pattern to not make them connect so much
and pr:next(1,8) == 1 then
local y = heightmap[hmi] -- ground y
if y > 4
and y >= minp.y
and y <= maxp.y then
if not pmap then
pmap = perlinmap:get2dMap_flat({x=x0, y=z0})
end
local noise = pmap[hmi]
if noise > 0.9
and (noise-0.9)*10 > pr:next(0,1000)/1000 then
if not vm then
local emin, emax
vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
area = VoxelArea:new{MinEdge=emin, MaxEdge=emax}
data = vm:get_data()
param2s = vm:get_param2_data()
end
if is_soil(data[area:index(x,y,z)]) then
flower_placed = true
make_flower(pr:next(3,7), pr, area, data, param2s, tag, z,y+1,x)
end
end
end
end
hmi = hmi+1
end
end
if not flower_placed then
return
end
local t2 = os.clock()
vm:set_data(data)
vm:set_param2_data(param2s)
vm:set_lighting({day=0, night=0})
vm:calc_lighting()
vm:write_to_map()
log("data set", 2, t2)
--[[
t2 = os.clock()
do_metas(tag)
log("metas set", 2, t2)--]]
log("done", 1, t1)
end)
local time = math.floor(tonumber(os.clock()-load_time_start)*100+0.5)/100
local msg = "[sun_flowers] loaded after ca. "..time
if time > 0.05 then
print(msg)
else
minetest.log("info", msg)
end