diff --git a/nc_sky_isgen/init.lua b/nc_sky_isgen/init.lua index 0021614..d7ed6b7 100644 --- a/nc_sky_isgen/init.lua +++ b/nc_sky_isgen/init.lua @@ -33,8 +33,8 @@ local pers = 0.9 local oct = 4 local noise = PerlinNoise{ - scale = maxval(oct,pers,32), - spread = {x=64,y=64,z=64}, + scale = maxval(oct,pers,128), + spread = {x=128,y=128,z=128}, seed=1297, octaves = oct, persistence = pers, @@ -42,6 +42,10 @@ local noise = PerlinNoise{ flags = "eased" } +local function sigmoid(z) + return 1/(1+math.exp(-z)) +end + local function island(pos,r,call) local x,y,z = pos.x,pos.y,pos.z minetest.emerge_area({x=x-r,y=y-r,z=z-r},{x=x+r,y=y+r,z=z+r},function(bp,act,crem) @@ -52,10 +56,10 @@ local function island(pos,r,call) local c = 0 local cm = (r*2+1)^3 local function geto(x1,y1,z1,n) - local r1 = 48+n*2-1 + local r1 = 48+n local dista = dist(0,0,0,x1,y1*3,z1) local m = math.max(0,1-dista/r1) - local r2 = -r1 + local r2 = -(sigmoid((48+n/2)/48*3)*56) if y1 <= 0 and y1 >= r2 then local r3 = (1-math.sin(y1/r2*math.pi/2))*r1 local distb = dist(0,y1,0,x1,y1,z1) @@ -130,8 +134,12 @@ local function raw_spawn_island(pos,call) end local function spawn_island(name,pos) local ref = minetest.get_player_by_name(name) - raw_spawn_island(pos) - ref:set_pos({x=pos.x,y=pos.y+256,z=pos.z}) + raw_spawn_island(pos,function() + local ref = minetest.get_player_by_name(name) + if ref then + ref:set_pos({x=pos.x,y=pos.y+64,z=pos.z}) + end + end) end local store = minetest.get_mod_storage() local players = minetest.deserialize(store:get_string("players")) or {} @@ -228,27 +236,33 @@ local function spawn_particles(x,y,z,player) end end local function checkpos(x,y,z,ch) - local mi,ma = islandgen_range(x,y,z) + local mi,ma = islandgen_range(f(x),f(y),f(z)) + print("requested check for pos "..x.." "..y.." "..z) minetest.emerge_area(mi,ma,function(bpos,act,crem) if crem > 0 then return end + print("checking pos "..x.." "..y.." "..z) local vm = VoxelManip(mi,ma) local emi,ema = vm:get_emerged_area() local dat = vm:get_data() local ar = VoxelArea:new{MinEdge=emi,MaxEdge=ema} + local v = true for x = mi.x,ma.x do for y = mi.y,ma.y do - for z = mi.y,ma.z do + for z = mi.z,ma.z do local d = dat[ar:index(x,y,z)] - if d ~= air_c and d ~= ignore_c then - ch(false) - return + if d ~= air_c then + v = false + break end end + if not v then break end end + if not v then break end end - ch(true) + print("running callback; v="..tostring(v)) + ch(v) end) end @@ -307,7 +321,7 @@ local function gen_island_pos(name,fgen) return end local x,y,z = 0,0,0 - x,z = x+math.random(-96,96),z+math.random(-96,96) + x,z = x+math.random(-64,64),z+math.random(-64,64) y=256+math.random(-32,32) if not fgen then for k,isl in pairs(cells) do @@ -319,46 +333,49 @@ local function gen_island_pos(name,fgen) players[name] = {pos = pos, valid = true} save() pos = {x=f(pos.x),y=f(pos.y),z=f(pos.z)} - ref:set_pos({x=pos.x,y=pos.y+256,z=pos.z}) + ref:set_pos({x=pos.x,y=pos.y+64,z=pos.z}) return end end end local function ch(ok) if not ok then - local sx,sz = math.random(-96,96),math.random(-96,96) + local sx,sz = math.random(-64,64),math.random(-64,64) if ((x+sx)^2+(z+sz)^2)^0.5 < (x^2+z^2)^0.5 then sx=-sx sz=-sz end x,z = x+sx,z+sz y=256+math.random(-32,32) - ok = checkpos(x,y,z,ch) + checkpos(x,y,z,ch) else local ip = {x=x,y=y,z=z} - if not fgen then - spawn_island(name,ip) - else - raw_spawn_island(ip,function() - ended = ended + 1 - if ended >= (fgen or 1) then - minetest.chat_send_player(name,S"Island generation done") - else - minetest.chat_send_player(name,S("Generated an island (@1%)"), math.floor(ended/(fgen or 1)*1000)/10) - end - minetest.after(0,gen,n+1) - end) - end - local pl = { - pos = ip, - valid = true - } - if not fgen then - players[name] = pl - else - table.insert(cells,pl) - end - save() + checkpos(x,y,z,function(ok) + assert(ok,"super-duper-error") + if not fgen then + spawn_island(name,ip) + else + raw_spawn_island(ip,function() + ended = ended + 1 + if ended >= (fgen or 1) then + minetest.chat_send_player(name,S"Island generation done") + else + minetest.chat_send_player(name,S("Generated an island (@1%)", math.floor(ended/(fgen or 1)*1000)/10)) + end + gen(n+1) + end) + end + local pl = { + pos = ip, + valid = true + } + if not fgen then + players[name] = pl + else + table.insert(cells,pl) + end + save() + end) end end checkpos(x,y,z,ch) @@ -380,7 +397,7 @@ minetest.register_globalstep(function(dt) to_upd = to_upd+updrate for k,ref in pairs(minetest.get_connected_players()) do local is = get_standing_island(ref:get_player_name()) - if is and is.t == cells and not minetest.check_player_privs(ref,{server = true}) then + if is and not minetest.check_player_privs(ref,{server = true}) then cells[is.k].valid = false end local p = ref:get_pos() @@ -395,7 +412,7 @@ minetest.register_globalstep(function(dt) gen_island_pos(ref:get_player_name()) end if pos then - pos.y=pos.y+256 + pos.y=pos.y+64 ref:set_pos(pos) end end @@ -575,78 +592,7 @@ minetest.register_chatcommand("islandgen",{ minetest.register_on_joinplayer(function(ref) local meta = ref:get_meta() local name = ref:get_player_name() - if meta:get_string("islandpos") ~= "" then - if not players[name] then - local pos = minetest.string_to_pos(meta:get_string("islandpos")) - local hascell = false - for k,v in pairs(players) do - if vector.length(vector.subtract(v.pos,pos)) < 8 then - hascell = true - break - end - end - while true do - local rem = false - for k,v in pairs(cells) do - if vector.length(vector.subtract(v.pos,pos)) < 8 then - table.remove(cells,k) - rem = true - break - end - end - if not rem then - break - end - end - if not hascell then - local pl = { - pos = pos, - valid = false - } - players[name] = pl - else - gen_island_pos(name) - end - end - save() - meta:set_string("island","") - meta:set_string("islandpos","") - meta:set_string("islandrange","") - else - if not players[name] then - gen_island_pos(name) - save() - else - local p = players[name] - if p.islandpos then - players[name] = {pos = p.islandpos, valid = false} - save() - end - local pos = players[name].pos - local hascell = false - for k,v in pairs(players) do - if vector.length(vector.subtract(v.pos,pos)) < 8 and k ~= name then - hascell = true - break - end - end - while true do - local rem = false - for k,v in pairs(cells) do - if vector.length(vector.subtract(v.pos,pos)) < 8 then - table.remove(cells,k) - rem = true - break - end - end - if not rem then - break - end - end - if hascell then - players[name] = nil - gen_island_pos(name) - end - end + if not players[name] then + gen_island_pos(name) end -end) \ No newline at end of file +end)